MagicMock @patch没有像我预期的那样工作

时间:2014-03-11 11:44:59

标签: python

(Python 2.6)

我在MagicMock补丁中遗漏了一些内容

给出以下生产代码:

class MyQueue(object):
    def send(self, message):
        pass

class MessageSender(object):
    def send_all(self, messages):
        queue = MyQueue()
        for message in messages:
            queue.send(message)

我有以下测试:

class MessageSenderTest(TestCase):
    @patch('path.to.MyQueue')
    def test_can_send_all_messages(self, queue):
        messages = ['foo', 'bar', 'baz']
        sender = MessageSender()
        sender.send_all(messages)
        queue.send.assert_has_calls([call(message) for message in messages])

这给了我:

AssertionError: Calls not found.
Expected: [call('foo'), call('bar'), call('baz')]
Actual: []        

我认为sender产生的模拟会让我做出断言。

1 个答案:

答案 0 :(得分:2)

请注意,您没有在测试方法中使用已修补的queue实例,因为它是由MessageSender类实例化的。这导致每次调用MyQueue方法时都会实例化模拟的send。实际上,您可以稍微修改一下断言并获取以下调用列表:

expected = [call()] + [call().send(message) for message in messages]
self.assertEquals(queue.mock_calls, expected)

在这种形式下,测试通过。但是,我认为MessageSender类在其构造函数方法中接收MyQueue会更自然,因此可以在测试中模拟它。请参阅此替代实施:

# file: main.py

class MyQueue(object):

    def send(self, message):
        pass


class MessageSender(object):

    def __init__(self, queue):
        self.queue = queue

    def send_all(self, messages):
        for message in messages:
            self.queue.send(message)

使用它,测试读起来更自然:

# file: test.py

import unittest

from mock import patch, call

import main


class MessageSenderTest(unittest.TestCase):

    @patch('main.MyQueue')
    def test_can_send_all_messages(self, queue):
        messages = ['foo', 'bar', 'baz']
        sender = main.MessageSender(queue)  # <-- here is where you do use `queue`
        sender.send_all(messages)
        queue.send.assert_has_calls([call.send(message) for message in messages])

if __name__ == '__main__':
    unittest.main()