I'm having some trouble understanding why the following code does not pass:
test.py
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
from bar import Bar
class Foo(object):
def add(self, x, y):
bar = Bar()
return bar.add(x, y)
bar.py
class Bar(object):
def add(self, x, y):
print('b.Bar --> Adding {} + {}'.format(x, y))
return x + y
In the code, Foo.add
creates an instance of Bar
and returns the result of Bar.add
when invoked. Why does testing assert_called_with
for Bar.add
fail? I believe I am mocking the Bar
in the correct place (I am mocking foo.Bar
because that is the namespace which it is being looked up, rather than bar.Bar
).
Traceback (most recent call last): File "/Users/iain/PycharmProjects/testing/venv/lib/python2.7/site-packages/mock.py", line 1201, in patched return func(*args, **keywargs) File "test.py", line 12, in test_a_b fake_Bar.add.assert_called_with(2, 2) File "/Users/iain/PycharmProjects/testing/venv/lib/python2.7/site-packages/mock.py", line 831, in assert_called_with raise AssertionError('Expected call: %s\\nNot called' % (expected,)) AssertionError: Expected call: add(2, 2) Not called
You are mocking the method call in the right place. However, since you are calling the method from an instance, it is a bound method, and thus receives the instance as the first argument (the self
parameter), in addition to all the other arguments.
Edit : Since Bar
is replaced with a Mock
instance, Bar().add
does not know it's a method (and hence is not bound to anything). In other words, Bar
is a Mock
, Bar()
is a Mock
, and Bar().add
is also a Mock
. bar.add
is thus a newly created mock, called with arguments (2, 2)
. One way of asserting this call would be:
@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)
Depending on how your actual code looks, you may want to instead mock the method rather than the class:
@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)
I believe your problem would be solved like this:
from bar import Bar
class Foo(object):
def add(self, x, y):
self.bar = Bar()
return self.bar.add(x, y)
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.