我在设置单元测试时遇到了很多困难。我一直在使用补丁,但它的表现并不像预期的那样。
我的测试功能顶部有一个装饰器:
@mock.patch('WarningFactory.WarningAPIUpdate')
@mock.patch('WarningFactory.SomethingElse')
def test_send_tc_update(self, other_mock, api_mock):
然而,当我尝试做出以下断言时,在我的函数结束时:
api_mock.send_warning.assert_called_with('IDQ20026', 'IDQ20026')
失败
我知道应该通过,因为我跑
print api_mock.mock_calls
给
[call(u'test_api'),
call().send_warning('IDQ20026', 'IDQ20026'),
call().send_warning('IDQ24500', 'IDQ24500')]
我可以清楚地看到使用正确的值调用send_warning方法,为什么我的断言失败?
答案 0 :(得分:4)
现在回想一下问题是assert_called_with只检查最近的呼叫。
assert_any_call(* args,** kwargs)¶断言模拟已被调用 指定的参数。
如果模拟被调用,则断言传递,不像 assert_called_with()和assert_called_once_with()只传递if 这个电话是最近的一个,而在这种情况下 assert_called_once_with()它也必须是唯一的调用。
文档有点狡猾,因为他们没有在assert_called_with方法下提到这一点。
我最终使用assert_any_call方法进行测试。
答案 1 :(得分:0)
如果user3559247's answer不起作用,则可能是您在尝试模拟嵌套对象,您将需要阅读有关chaining mock calls的信息。就我而言,我想在假设类MyAzureBatchClient
中利用Azure Python SDK测试此代码:
def node_counts():
self.batch_client = azure.batch.batch_service_client.BatchServiceClient(...)
self.batch_client.account.list_pool_node_counts()
...
调用mocked_batch_client.account.list_pool_node_counts.assert_called_with()
失败,尽管检查mock_calls
属性会显示与您类似的内容:
[call().list_pool_node_counts()]
但是,与mocked_batch_client.return_value.account.list_pool_node_counts.assert_called_with()
正确链接时,它可以按预期工作。检查mocked_batch_client.return_value.account.mock_calls
时,请注意call.method
的存在方式,而不是call().method
:
[call.list_pool_node_counts()]
答案 2 :(得分:0)
根据您提到的打印输出,语法可能应该是:
api_mock.return_value.send_warning.assert_called_with('IDQ20026', 'IDQ20026')
注意 call()。send_warning('IDQ20026', 'IDQ20026')
前缀,它与.return_value
相关。
但是为什么要这么努力?我写了helper library为我自动生成断言。
只需添加这些行即可为您的案例打印正确的断言:
import mock_autogen.generator
print(mock_autogen.generator.generate_asserts(api_mock))