user3559247
user3559247

Reputation: 1228

Why is assert_called_with failing to pass?

I am having a lot of difficulty setting my unit test. I have been using patch but it is not behaving entirely as expected.

I have a decorator at the top of my test function: @mock.patch('WarningFactory.WarningAPIUpdate') @mock.patch('WarningFactory.SomethingElse') def test_send_tc_update(self, other_mock, api_mock):

However when at the end of my function when I try to make the following assertion:

api_mock.send_warning.assert_called_with('IDQ20026', 'IDQ20026')

It fails

I know that is should pass because I run

print api_mock.mock_calls

giving

[call(u'test_api'), call().send_warning('IDQ20026', 'IDQ20026'), call().send_warning('IDQ24500', 'IDQ24500')]

I can clearly see the send_warning method being called with the correct values, so why is my assertion failing?

Upvotes: 9

Views: 11157

Answers (3)

Peter K
Peter K

Reputation: 2484

Based on the print output you mentioned the syntax should probably be:

api_mock.return_value.send_warning.assert_called_with('IDQ20026', 'IDQ20026')

Notice the call().send_warning('IDQ20026', 'IDQ20026') prefix, which correlates to .return_value.

But why work so hard? I wrote a helper library to automatically generate the asserts for me.

Just add those lines to print the correct asserts for your case:

import mock_autogen.generator
print(mock_autogen.generator.generate_asserts(api_mock))

Upvotes: 0

Stewart Adam
Stewart Adam

Reputation: 343

If user3559247's answer does not work, it may be that you're trying to mock nested objects and you will need to read about chaining mock calls. In my case, I wanted to test this code in a hypothetical class MyAzureBatchClient that leverages the Azure Python SDK:

def node_counts():
  self.batch_client = azure.batch.batch_service_client.BatchServiceClient(...)
  self.batch_client.account.list_pool_node_counts()
  ...

Calling mocked_batch_client.account.list_pool_node_counts.assert_called_with() failed, although checking the mock_calls property would showed something similar to you:

[call().list_pool_node_counts()]

However when properly chaining with mocked_batch_client.return_value.account.list_pool_node_counts.assert_called_with() it works as expected. When checking mocked_batch_client.return_value.account.mock_calls, note how call.method is present instead of call().method: [call.list_pool_node_counts()]

Upvotes: 0

user3559247
user3559247

Reputation: 1228

Looking back now the problem was that assert_called_with only checks the most recent call.

assert_any_call(*args, **kwargs)¶ assert the mock has been called with the specified arguments.

The assert passes if the mock has ever been called, unlike assert_called_with() and assert_called_once_with() that only pass if the call is the most recent one, and in the case of assert_called_once_with() it must also be the only call.

The docs are a little dodgy as they don't mention this under the assert_called_with method.

I ended up using the assert_any_call method for my tests.

Upvotes: 11

Related Questions