正确的方法来模拟类和断言对方法的调用

时间:2015-12-03 13:18:13

标签: python python-2.7 unit-testing mocking python-unittest

我正在尝试为Bar编写调用Foo方法read()的单元测试。我在setUp()中添加了patch命令,因为其他测试也会使用此补丁。

问题

如何使用我期望的参数检查read()函数是否被调用?

代码

foo.py
class Foo(object):
    def __init__(self):
        self.table = {'foo': 1}

    def read(self, name):
        return self.table[name]
bar.py
import foo

class Bar(object):
    def act(self):
        a = foo.Foo()
        return a.read('foo')
test_bar.py
import bar
import unittest
from mock import patch

class TestBar(unittest.TestCase):
    def setUp(self):
        self.foo_mock = patch('bar.foo.Foo', autospec=True).start()
        self.addCleanup(patch.stopall)

    def test_can_call_foo_with_correct_arguments(self):
        a = bar.Bar()
        a.act()
        self.foo_mock.read.assert_called_once_with('foo')

输出

python -m unittest discover
F
======================================================================
FAIL: test_can_call_foo_with_correct_arguments (test_bar.TestBar)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/test_dir/test_bar.py", line 12, in test_can_call_foo_with_correct_arguments
    self.foo_mock.read.assert_called_once_with('foo')
  File "/usr/local/lib/python2.7/dist-packages/mock.py", line 845, in assert_called_once_with
    raise AssertionError(msg)
AssertionError: Expected to be called once. Called 0 times.

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

2 个答案:

答案 0 :(得分:4)

Fooreturn_value实例上的一种方法。您想检查模拟foo.Foo()以访问该实例。毕竟,您可以通过调用 foo_instance = self.foo_mock.return_value foo_instance.read.assert_called_once_with('foo') 创建实例:

foo.Foo

请注意,您正在修补bar.foo.Foo;使用 'Session' => [ 'defaults' => 'php', 'timeout' => '2000', 'ini' => [ 'session.cookie_domain' => '.domain.com', 'session.save_path' => '/var/www/clients/web/tmp', 'session.name' => 'PHPSESSID' ] ], 是同一个对象,但是用于指定它的循环方式。

答案 1 :(得分:0)

Mo子有很多陷阱,这就是为什么I wrote a helper library为我生成断言的原因。

要使用它,您应该在a.act()之后添加以下几行:

import mock_autogen.generator
print(mock_autogen.generator.generate_asserts(mock=self.foo_mock, name='self.foo_mock'))

这将输出以下行:

assert 1 == self.foo_mock.call_count
self.foo_mock.assert_called_once_with()
self.foo_mock.return_value.read.assert_called_once_with('foo')

由于foo是实例化的类,因此生成了前两个。第三行是您最初要查找的行。

因此,不再需要猜测,要有条理,并使用mock-generator