Python的assert_has_calls抛出AssertionError,找不到调用

时间:2017-04-12 19:53:51

标签: python unit-testing mocking

我正在尝试编写一个单元测试来测试我的协调器类的函数,以便将数据发送给我已经模拟过的生产者。我有点疯狂添加打印语句来查看发生了什么,我不确定这是否有用,但我将包括那些。实际的模拟似乎是通过查看print语句来工作,但是我的assert_has_calls会抛出一个Assertion Error,找不到调用。我做错了什么?

我使用的是Python 2.7.10和Mock 2.0.0

这是我的测试:

@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)

这是输出:

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)]

修改

为了看看会发生什么,我还尝试将assert语句更改为mock_producer.assert_has_calls(mock_producer.mock_calls),但失败并出现错误:

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')]

基于模拟文档,我认为应该成功,因为assert_has_calls将期望值与mock_calls列表中的值进行比较。这个逻辑是不正确的?

1 个答案:

答案 0 :(得分:0)

所以事实证明,因为我正在调用我在类中创建的生成器对象,我正在测试模拟被记录在第二个模拟对象下。我得到了两个:测试类中的一个mock_producer和另一个名为myproducer的模拟生产者(我在我的类中使用的名称,我正在测试)。

@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)

因此,如果我改变语句以引用第二个模拟生成器,我的测试就会通过。例如:

assert coor.myproducer.send_message.called is True

而不是

assert mock_producer.called is True