I have a class with some properties. In my test, I need to set up a fixture, and have the properties mocked. However, the patch only works in the fixture function, not when the fixture is called. Any idea how to fix this?
Here is the simplified version of the problem. Let's assume that this is my class Panda
:
class Panda(object):
def __init__(self, name):
self.panda_name = name
@property
def name(self):
return self.panda_name
and this is my test
import pytest
from unittest.mock import patch, PropertyMock
from tmp import Panda
@pytest.fixture
@patch(
'tmp.Panda.name',
new_callable=PropertyMock,
return_value="yuanyuan")
def fixture_panda(mk_name):
p = Panda("this name should not matter")
print(p.name) # print "yuanyuan"
return p
def test_panda_fixture(fixture_panda):
p = fixture_panda
print(p.name) # print "this name should not matter"
# this test fails
assert p.name == "yuanyuan"
The first print function in fixture_panda
would print yuanyuan
, which means the propertyMock works as expected. However the 2nd print function in test_panda_fixture
print this name should not matter
, which means the propertyMock doesn't work here. Any idea why this happens and how to fix this?
If you want to monkeypatch something in pytest
, you can use their built-in fixture monkeypatch
, which can be inserted into all fixtures with scope = function
. Here is an example from my codebase:
@pytest.fixture(scope="function", autouse=True)
def no_jwt(monkeypatch):
"""Monkeypatch the JWT verification functions for tests"""
monkeypatch.setattr("flask_jwt_extended.verify_jwt_in_request", lambda: print("Verify"))
If I apply it to your example, I think something like this should work:
@pytest.fixture
def fixture_panda(monkeypatch, mk_name):
monkeypatch.setattr('tmp.Panda.name', "yuanyuan")
p = Panda("this name should not matter")
print(p.name) # print "yuanyuan"
return p