I am trying to use side_effect
with unittest.mock.create_autospec
on class to set default instance call behavior to raise NotImplementedError
.
The problem I am facing is:
__init__
.pytest.fixture
in order to make my mock reusable through various tests.Here a code sample of what I am trying to achieve.
# module.py
class MyClass:
def __init__(self, value):
self.value = value
def compute(self):
return self.value
def foo():
instance = MyClass(42)
return instance.compute()
# test_module.py
from unittest.mock import create_autospec
import module
import pytest
@pytest.fixture(autouse=True)
def my_class(monkeypatch):
# Help me HERE to set side_effect, bellow tests will not work with this settings.
spec_cls = create_autospec(module.MyClass, side_effect=NotImplementedError)
monkeypatch.setattr(module, "MyClass", spec_cls)
return spec_cls("<whatever>")
def test_foo():
with pytest.raises(NotImplementedError):
module.foo()
def test_bar(my_class):
my_class.compute.return_value = 24
assert module.foo() == 24
Not need to use autospec
:
import unittest.mock as mocking
import pytest
import so71018132_module as module
@pytest.fixture(autouse=True)
def fake_my_class():
with mocking.patch.object(module.MyClass, "compute") as compute_mock:
compute_mock.side_effect = NotImplementedError # default behaviour
yield compute_mock
def test_foo():
with pytest.raises(NotImplementedError):
module.foo()
def test_bar(fake_my_class):
fake_my_class.side_effect = [24]
# or alternatively, clear the side_effect then set a return_value :
# fake_my_class.side_effect = None
# fake_my_class.return_value = 24
assert module.foo() == 24
passes the 2 tests.
I completely changed the fixture to use unittest.mock.object.patch
on the compute
method of MyClass
so just that is mocked, the rest of the class is used ordinarily.
Also, I had to slightly adjust the test_bar
code to correctly alter the mock behavior.