Reputation: 2668
I'm using unittest.mock
, this wonderful library. However I was surprised by an unexpected behavior, and I don't see an obvious solution. I'm using it for my unit tests and it is vital to understand perfectly how it behaves to have useful tests.
I know the code below in show_bar
is broken, it is calling a classmethod instead of the instance method. However, all my mock
unittests are passing :
Code containing a bug:
class Foo(object):
def bar(self):
return "bar"
def show_bar(self):
return Foo.bar()
Expected usage:
foo = Foo()
assert foo.show_bar() == "bar"
# => throw exception: bar() missing 1 required positional argument: 'self'
Unittest tries unsuccessfully to catch this error with mock
:
from unittest.mock import patch
with patch.object(Foo, 'bar', return_value="bar") as mock:
foo = Foo()
assert foo.show_bar() == "bar"
mock.assert_called_once()
# => no errors
Ideally, I would like to assert that bar
is called with self.bar()
and NOT Foo.bar()
; which is wrong. Unfortunately, using mock.assert_called_with()
does not take in account the self
nor cls
parameter, so I'm a bit confused.
EDIT: Trying to clarify. I'm looking for best practices to use the library unittest.mock
when we need to patch an object's method. It seems not clear to me how to patch it, currently I have no way to assert if it's calling self.bar
or Foo.bar
.
Upvotes: 4
Views: 1955
Reputation: 77912
I don't really understand why you'd need to mock the method to test that it does not raise a TypeError when called but anyway... Someone else might explain how to solve this using unittest.mock
, in the meantime you can just skip unittest.mock
and mock Foo.bar
by yourself:
callargs = dict()
def mock_bar(self):
callargs["self"] = self
return "bar"
foobar = Foo.__dict__["bar"]
Foo.bar = mock_bar
try:
foo = Foo()
assert foo.show_bar() == "bar"
assert "self" in callargs
assert callargs["self"] is foo
finally:
Foo.bar = foobar
Upvotes: 1