关于单元测试:在Python中模拟assert_called_with

Mocking assert_called_with in Python

我在理解以下代码未通过的原因时遇到了一些麻烦:

test.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import mock
import unittest

from foo import Foo


class TestFoo(unittest.TestCase):
    @mock.patch('foo.Bar')
    def test_foo_add(self, Bar):
        foo = Foo()
        foo.add(2, 2)
        Bar.add.assert_called_with(2, 2)


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

foo.py

1
2
3
4
5
6
from bar import Bar

class Foo(object):
    def add(self, x, y):
        bar = Bar()
        return bar.add(x, y)

bar.py

1
2
3
4
class Bar(object):
    def add(self, x, y):
        print('b.Bar --> Adding {} + {}'.format(x, y))
        return x + y

在代码中,Foo.add创建Bar的实例,并在调用时返回Bar.add的结果。 为什么Bar.addassert_called_with测试失败? 我相信我在正确的位置嘲笑Bar(我正在嘲笑foo.Bar,因为这是它被查找的命名空间,而不是bar.Bar)。

Traceback(最近一次调用最后一次):
文件"/Users/iain/PycharmProjects/testing/venv/lib/python2.7/site-packages/mock.py",第1201行,已修补
return func(* args,** keywargs)
在test_a_b中输入第12行的"test.py"
fake_Bar.add.assert_called_with(2,2)
在assert_called_with中输入文件"/Users/iain/PycharmProjects/testing/venv/lib/python2.7/site-packages/mock.py",第831行
引发AssertionError('预期调用:%s n不要调用'%(expected,))
AssertionError:预期调用:add(2,2)
不叫


你正在嘲笑方法调用在正确的地方。 但是,由于您是从实例调用该方法,因此它是一个绑定方法,因此除了所有其他参数外,还接收实例作为第一个参数(self参数)。

编辑:由于BarMock实例替换,Bar().add不知道它是一个方法(因此没有绑定任何东西)。 换句话说,BarMockBar()MockBar().add也是Mock。 因此,bar.add是一个新创建的模拟,使用参数(2, 2)调用。 断言此调用的一种方法是:

1
2
3
4
5
@mock.patch('foo.Bar')
def test_foo_add(self, Bar):
    foo = Foo()
    foo.add(2, 2)
    Bar.return_value.add.assert_called_with(2, 2)

根据您的实际代码的外观,您可能希望模拟方法而不是类:

1
2
3
4
5
@mock.patch('foo.Bar.add')
def test_foo_add(self, bar_add):
    foo = Foo()
    foo.add(2, 2)
    bar_add.assert_called_with(2, 2)


我相信你的问题会像这样解决:

1
2
3
4
5
6
from bar import Bar

class Foo(object):
    def add(self, x, y):
        self.bar = Bar()
        return self.bar.add(x, y)