Is it possible to use the library with pytest.fixture and MagicMock? #31
-
Hi! I see a lot of potential in this library. I have a use case scenario where I need to use the class TestMyInstance:
@pytest.fixture
def agent(self):
agent = MagicMock(spec=CompiledGraph)
when(agent, "invoke").called_with(
{"messages": [{"role": "user", "content": "hello"}]},
).then_return({"messages": [AIMessage(id="a", content="Hello world!")]})
return agent
@pytest.fixture
def instance(self, agent):
return MyInstance.from_agent(
agent=agent
)
def test_involke(self, instance):
result = instance.invoke(...)
assert result == "my expected result" Is there a way to make the library working for this use case? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
Hi @samuelint , thanks for the feedback and your question. I'll take a look to it tomorrow and get back here. |
Beta Was this translation helpful? Give feedback.
-
Next time please care about others' time and give a reproducible code that I can run locally without any extra editions. From what I see, there is no problem with pytest-when in this case and it can support your use case without any limitations. The core problem in your code was wrong call to when fixture and fixtures compositions. when fixture, identically to unittest.mock.patch.object, takes Klass as target Then you had issue with fixtures composition in your fixtures. Working solution from typing import NamedTuple
import pytest
from pytest_mock import MockerFixture
from pytest_when.when import When
class AIMessage(NamedTuple):
id: str
content: str
class CompiledGraph:
@classmethod
def from_agent(
cls,
agent: "CompiledGraph",
) -> "MyInstance":
return cls()
def invoke(self, messages: list[AIMessage]): ...
class TestMyInstance:
@pytest.fixture()
def agent(self, when: When, mocker: MockerFixture):
agent = mocker.MagicMock(spec=CompiledGraph)
when(CompiledGraph, "invoke").called_with(
messages=[{"role": "user", "content": "hello"}]
).then_return(
{"messages": [AIMessage(id="a", content="Hello world!")]}
)
return agent
@pytest.fixture()
def instance(self, agent):
return CompiledGraph.from_agent(agent=agent)
def test_involke(self, instance):
result = instance.invoke(
messages=[{"role": "user", "content": "hello"}]
)
assert result == {
"messages": [AIMessage(id="a", content="Hello world!")]
} |
Beta Was this translation helpful? Give feedback.
-
Thanks for taking time to find a solution. However, I was wondering if it was possible to pass the magic mock instance to the when function. Instead of declaring the class type (CompiledGraph in this case). agent = MagicMock(spec=CompiledGraph)
when(agent, "invoke") From what I understand, it's not possible :) This library resembles a lot like https://www.npmjs.com/package/jest-when (typescript/javascript), where it's possible to pass instance of the mocked object. I think being able to do the same would be a great add-on :) That's something we often see in other languages testing framework, but does not seem to be the case in python. |
Beta Was this translation helpful? Give feedback.
Next time please care about others' time and give a reproducible code that I can run locally without any extra editions.
From what I see, there is no problem with pytest-when in this case and it can support your use case without any limitations.
The core problem in your code was wrong call to when fixture and fixtures compositions. when fixture, identically to unittest.mock.patch.object, takes Klass as target
(type hints are (cls: _TargetClsType, method: str)). So instead of when(agent, ...) you need to have when(CompiledGraph, ...).
Then you had issue with fixtures composition in your fixtures.
Working solution