How do I get a method of a @patch
'ed class to throw an Exception when called?
B
is just a class that you can call go()
on, which in turn just prints that it happened:
# module_b.py
class B:
def __init__(self) -> None:
self.x = True
print("B constructed OK")
def go(self):
print("called B.go()")
A
is a class that holds an instance of B
. It also has a go()
method, which calls the B
instance's go()
method:
# module_a.py
from module_b import B
class A:
def __init__(self) -> None:
try:
self.b = B()
print("A constructed OK")
except Exception as e:
print("A's constructor threw an exception: " + repr(e))
def go(self):
try:
self.b.go()
print("b.go() called with no problems")
except Exception as e:
print("a.go() threw an exception: " + repr(e))
And here's the test code:
# main.py
from module_a import A
from module_b import B
from unittest import mock
# a = A()
# a.go() # output: called B.go()
@mock.patch("module_a.B") # learned the hard way to do this, not "module_b.B"
def test_b_constructor_throws(mock_b: mock.Mock):
mock_b.side_effect = Exception("test")
a = A()
print("-- test_b_constructor_throws() --")
test_b_constructor_throws()
print("")
@mock.patch("module_b.B.go")
@mock.patch("module_a.B")
def test_b_method_go_throws_1(
mock_b: mock.Mock,
mock_b_go: mock.Mock
):
# --- attempt 1 ---
# mock_b_go.side_effect = Exception("test")
# a = A()
# a.go()
# --- attempt 2 ---
mock_b.return_value.mock_b_go.side_effect = Exception("test")
a = A()
a.go()
print("-- test_b_method_go_throws_1() --")
test_b_method_go_throws_1()
print("")
Finally, here's the output:
-- test_b_constructor_throws() --
B's constructor threw an exception: Exception('test')
-- test_b_method_go_throws_1() --
A constructed OK
b.go() called with no problems
I've tried a variety of other things too, like autospec=True
and using @patch.object()
instead, but no go. I've read a bunch of seemingly related questions but have been unable to come up with a solution:
- Using Mock.side_effect for an instance method
- Why does mock ignore the instance/object passed to a mocked out method when it is called?
- python side_effect - mocking behavior of a method
- Pytest: Mock multiple calls of same method with different side_effect
- How do I mock a method on an object created by an @patch decorator?