Python pytest mock 失败,函数调用断言为 "assert None"

标签 python unit-testing pytest pytest-mock

我正在尝试模拟对 boto3 的一些调用,看起来被模拟的函数返回了正确的值,看起来如果我更改断言使其不再匹配断言中传递的内容失败,因为输入参数不匹配,但是如果我让它们匹配,那么断言失败:

E       AssertionError: assert None
E        +  where None = <bound method wrap_assert_called_with of <MagicMock name='get_item' id='139668501580240'>>(TableName='TEST_TABLE', Key={'ServiceName': {'S': 'Site'}})
E        +    where <bound method wrap_assert_called_with of <MagicMock name='get_item' id='139668501580240'>> = <MagicMock name='get_item' id='139668501580240'>.assert_called_with
E        +      where <MagicMock name='get_item' id='139668501580240'> = <botocore.client.DynamoDB object at 0x7f071b8251f0>.get_item
E        +        where <botocore.client.DynamoDB object at 0x7f071b8251f0> = site_dao.ddb_client
dynamo DB 对象是一个全局变量。
ddb_client = boto3.client("dynamodb")

def query_ddb():
        """Query dynamo DB for the current strategy.

        Returns:
            strategy (str): The latest strategy from dynamo DB.

        """
        response = None

        try:
            ddb_table = os.environ["DDB_DA_STRATEGY"]

            response = ddb_client.get_item(
                TableName=ddb_table, Key={"ServiceName": {"S": "Site"}}
            )
        except Exception as exception:
            LOGGER.error(exception)

            raise ServerException("The server was unable to process your request.", [])

        return response.get("Item").get("Strategy").get("S")
我的单元测试看起来像:
def test_data_access_context_strategy_ddb(mocker):
    object_key = {
        "ServiceName": {"S": "Site"}
    }

    table_name = "TEST_TABLE"

    expected_response = "SqlServer"

    os_env = {
        "DDB_DA_STRATEGY": table_name,
    }

    ddb_response = {
        "Item": {
            "Strategy": {
                "S": expected_response
            }
        }
    }

    mocker.patch.dict(os.environ, os_env)

    mocker.patch.object(site_dao.ddb_client, "get_item")

    site_dao.ddb_client.get_item.return_value = ddb_response

    data_access_context = site_dao.DataAccessContext()

    response = data_access_context.query_ddb()
    
    assert response == expected_response

    assert site_dao.ddb_client.get_item.assert_called_with(TableName=table_name, Key=object_key)
如果我更改 assert_called_with 的预期值,我无法弄清楚出了什么问题,例如:
assert site_dao.ddb_client.get_item.assert_called_with(TableName="TT", Key=object_key)
测试失败:
E       AssertionError: expected call not found.
E       Expected: get_item(TableName='TT', Key={'ServiceName': {'S': 'Site'}})
E       Actual: get_item(TableName='TEST_TABLE', Key={'ServiceName': {'S': 'Site'}})
E       
E       pytest introspection follows:
E       
E       Kwargs:
E       assert {'Key': {'Ser... 'TEST_TABLE'} == {'Key': {'Ser...leName': 'TT'}
E         Omitting 1 identical items, use -vv to show
E         Differing items:
E         {'TableName': 'TEST_TABLE'} != {'TableName': 'TT'}
E         Use -v to get the full diff
因此,当预期和实际输入不同时,它会因此而失败,但是当它们相同并且测试应该通过时,它就会失败,因为就好像该函数从未被调用过一样。

最佳答案

你在这一行有两个断言:

assert site_dao.ddb_client.get_item.assert_called_with(TableName=table_name, Key=object_key)
第一个断言是 assert_called_with这听起来像是你想要的。然后在该行的开头有另一个断言:assert ...断言 assert_called_with 的返回值功能。该返回值是 null当断言通过时。那么整行的计算结果为 assert null .
tl;dr 不要使用 assert两次。

关于Python pytest mock 失败,函数调用断言为 "assert None",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63266504/

相关文章:

python - 为什么 Keras 层定义使用嵌套函数?

python - Pandas:计算大写单词的数量

java - 在 Robolectric 测试中注入(inject)模拟

python - 同时使用 pytest 和 tf.test.TestCase 的问题

python - 如何使用 Nginx 将 404 请求重定向到 Django 单页应用程序中的主页?

python - 编写交互式 FTP 登录脚本

c# - 起订量参数 TargetParameterCountException : Parameter count mismatch Exception

.net - NUnit 全局初始化 - 坏主意?

python - 如何在 Django 中使用 `DEBUG=TRUE` 运行测试

python - Pytest cov 不生成任何报告