简体   繁体   中英

Python's assert_has_calls throws AssertionError that calls were not found

I am trying to write a unit test that tests my coordinator class' function for sending data to a producer that I have mocked. I went a little crazy adding print statements to see what is going on where, and I'm not sure if that is useful but I'm going to include those. The actual mocking seems to be working from looking at the print statements, however my assert_has_calls throws an Assertion Error that calls were not found. What did I do wrong?

I am using Python 2.7.10 and Mock 2.0.0

Here is my test:

@mock.patch('mypackage.producer.Producer', autospec=True)
def test_send_data(self, mock_producer):
    coor = mypackage.MyCoordinator()
    # Make sure we initialized the mocked producer with no values
    mock_producer.assert_called_with(None, None, None, None)

    # Create some data and send it to the producer
    for count in range(11):
        jsonToSend = {"objectID": 'test{}'.format(count)}
        coor.send_data(jsonToSend, None)
        print 'Sent message %s' % (jsonToSend) 

    # Verify the producer was called
    assert mock_producer.called is True

    print '\nMethod Calls:'
    print mock_producer.method_calls
    print '\nCall Args List:'
    print mock_producer.call_args_list
    print mock_producer.send_message.call_args_list
    print '\nAll Calls:'
    print mock_producer.mock_calls

    calls = [
        mock.call().start(),
        mock.call().send_message({"objectID": "test1"}, None),
        mock.call().send_message({"objectID": "test2"}, None),
        mock.call().send_message({"objectID": "test3"}, None)]

    # Verify that the mocks have been called correctly
    mock_producer.assert_has_calls(calls)

Here is the output:

Sent message {'objectID': 'test0'}
Sent message {'objectID': 'test1'}
Sent message {'objectID': 'test2'}
Sent message {'objectID': 'test3'}
Sent message {'objectID': 'test4'}
Sent message {'objectID': 'test5'}
Sent message {'objectID': 'test6'}
Sent message {'objectID': 'test7'}
Sent message {'objectID': 'test8'}
Sent message {'objectID': 'test9'}
Sent message {'objectID': 'test10'}

Method Calls:
[call().start(),
 call().send_message({'objectID': 'test0'}, None),
 call().send_message({'objectID': 'test1'}, None),
 call().send_message({'objectID': 'test2'}, None),
 call().send_message({'objectID': 'test3'}, None),
 call().send_message({'objectID': 'test4'}, None),
 call().send_message({'objectID': 'test5'}, None),
 call().send_message({'objectID': 'test6'}, None),
 call().send_message({'objectID': 'test7'}, None),
 call().send_message({'objectID': 'test8'}, None),
 call().send_message({'objectID': 'test9'}, None),
 call().send_message({'objectID': 'test10'}, None)]

Call Args List:
[call(None, None, None, None)]
[]

All Calls:
[call(None, None, None, None),
 call().start(),
 call().send_message({'objectID': 'test0'}, None),
 call().send_message({'objectID': 'test1'}, None),
 call().send_message({'objectID': 'test2'}, None),
 call().send_message({'objectID': 'test3'}, None),
 call().send_message({'objectID': 'test4'}, None),
 call().send_message({'objectID': 'test5'}, None),
 call().send_message({'objectID': 'test6'}, None),
 call().send_message({'objectID': 'test7'}, None),
 call().send_message({'objectID': 'test8'}, None),
 call().send_message({'objectID': 'test9'}, None),
 call().send_message({'objectID': 'test10'}, None)]
======================================================================
FAIL: test_send_data (kafka_api_test.KafkaApiTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Anaconda2\lib\site-packages\mock\mock.py", line 1305, in patched
    return func(*args, **keywargs)
  File "C:/Users/myuser/workspace/MyProject/tests/my_test.py", line 76, in test_send_data
    mock_producer.assert_has_calls(calls)
  File "C:\Anaconda2\lib\site-packages\mock\mock.py", line 969, in assert_has_calls
    ), cause)
  File "C:\Anaconda2\lib\site-packages\six.py", line 718, in raise_from
    raise value
AssertionError: Calls not found.
Expected: [call().start(),
 call().send_message({'objectID': 'test1'}, None),
 call().send_message({'objectID': 'test2'}, None),
 call().send_message({'objectID': 'test3'}, None)]
Actual: [call(None, None, None, None),
 call().start(),
 call().send_message({'objectID': 'test0'}, None),
 call().send_message({'objectID': 'test1'}, None),
 call().send_message({'objectID': 'test2'}, None),
 call().send_message({'objectID': 'test3'}, None),
 call().send_message({'objectID': 'test4'}, None),
 call().send_message({'objectID': 'test5'}, None),
 call().send_message({'objectID': 'test6'}, None),
 call().send_message({'objectID': 'test7'}, None),
 call().send_message({'objectID': 'test8'}, None),
 call().send_message({'objectID': 'test9'}, None),
 call().send_message({'objectID': 'test10'}, None)]

EDIT:

Just to see what happens I also tried changing the assert statement to mock_producer.assert_has_calls(mock_producer.mock_calls) but that fails with the error:

Traceback (most recent call last):
  File "C:\Anaconda2\lib\site-packages\mock\mock.py", line 1305, in patched
    return func(*args, **keywargs)
  File "C:/Users/myuser/workspace/MyProject/tests/my_test.py", line 73, in test_send_data
    mock_producer.assert_has_calls(mock_producer.mock_calls)
  File "C:\Anaconda2\lib\site-packages\mock\mock.py", line 969, in assert_has_calls
    ), cause)
  File "C:\Anaconda2\lib\site-packages\six.py", line 718, in raise_from
    raise value
AssertionError: Calls not found.
Expected: [call(None, None, None, None),
 call().start(),
 call().send_message({'objectID': 'test0'}, None),
 call().send_message({'objectID': 'test1'}, None),
 call().send_message({'objectID': 'test2'}, None),
 call().send_message({'objectID': 'test3'}, None),
 call().send_message({'objectID': 'test4'}, None),
 call().send_message({'objectID': 'test5'}, None),
 call().send_message({'objectID': 'test6'}, None),
 call().send_message({'objectID': 'test7'}, None),
 call().send_message({'objectID': 'test8'}, None),
 call().send_message({'objectID': 'test9'}, None),
 call().send_message({'objectID': 'test10'}, None),
 call().send_message({'objectID': 'test11'}, 'done')]
Actual: [call(None, None, None, None),
 call().start(),
 call().send_message({'objectID': 'test0'}, None),
 call().send_message({'objectID': 'test1'}, None),
 call().send_message({'objectID': 'test2'}, None),
 call().send_message({'objectID': 'test3'}, None),
 call().send_message({'objectID': 'test4'}, None),
 call().send_message({'objectID': 'test5'}, None),
 call().send_message({'objectID': 'test6'}, None),
 call().send_message({'objectID': 'test7'}, None),
 call().send_message({'objectID': 'test8'}, None),
 call().send_message({'objectID': 'test9'}, None),
 call().send_message({'objectID': 'test10'}, None),
 call().send_message({'objectID': 'test11'}, 'done')]

Based on the mock documentation, I would think that that should have succeeded since assert_has_calls compares the expected values with those in the mock_calls list. Is that logic incorrect?

So it turns out that since I was calling the producer object that I was creating in the class I was testing the mocks were being recorded under a second mocked object. I'm getting two of them: one mock_producer in the test class and a second mocked producer called myproducer (the name I used in my class I'm testing).

@mock.patch('mypackage.mycoordinator.producer.Producer') # This creates the first mocked object
@mock.patch('mypackage.mycoordinator.consumer.Consumer')
def test_send_data(self, mock_consumer, mock_producer):

class MyCoordinator():

def __init__(self):
    # Initialize the producer
    self.myproducer = producer.Producer(...) # This creates a second mocked object called myproducer

# Send the data to the producer
def send_data(self, data_to_send, key):
    self.myproducer.send_message(data_to_send, key)

So if I change the statements to refer to the second mocked producer instead, my test passes. For example:

assert coor.myproducer.send_message.called is True

instead of

assert mock_producer.called is True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM