For use in Pytest, I would like to create a spy of the magic method __call__
of a class.
Here is a minimal example. Code base:
import pytest
from pytest_mock import MockFixture, MockType
class A:
def __call__(self, x) -> None:
print("__call__", x)
class B:
def __init__(self, a: A) -> None:
self.a = a
def apply_a(self) -> None:
self.a(42)
Test code:
@pytest.fixture
def a() -> A:
return A()
@pytest.fixture
def b(a: A) -> B:
return B(a)
@pytest.fixture
def a_application_spy(mocker: MockFixture, a: A) -> MockType:
return mocker.spy(a, "__call__")
def test_apply_a(b: B, a_application_spy: MockType) -> None:
b.apply_a()
assert a_application_spy.called
The test test_apply_a
fails.
The reason seems to be that the method __call__
is a magic method, which is used implicitly. The test succeeds if the implementation of B.apply_a
is changed to
def apply_a(self) -> None:
self.a.__call__()
Is there a possibility to create the spy without having to change the code base?
This is a simple case of spying the wrong thing.
Instead of:
return mocker.spy(a, "__call__")
You want:
return mocker.spy(A, "__call__")