5

I usually can patch methods of normal objects using pytest monkeypatch. However when I try with a pydantic.BaseModel it fails.

from pydantic import BaseModel
class Person(BaseModel):
 name: str
 age: int
 def intro(self) -> str:
 return f"I am {self.name}, {self.age} years old."
def test_person_intro(monkeypatch):
 p = Person(name='Joe', age=20)
 monkeypatch.setattr(p, 'intro', lambda: 'patched intro')
 assert p.intro() == 'patched intro'

Raises:

monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x10f0d3040>
 def test_intro(monkeypatch):
 p = Person(name='Joe', age=20)
> monkeypatch.setattr(p, 'intro', lambda: 'patched intro')
- - - - - - - - - - - - - - - - - - - - - 
> ???
E ValueError: "Person" object has no field "intro"
pydantic/main.py:422: ValueError
asked Mar 21, 2023 at 16:56

2 Answers 2

5

You could patch the type:

def test_person_intro(monkeypatch):
 p = Person(name='Joe', age=20)
 monkeypatch.setattr(Person, 'intro', lambda self: 'patched intro')
 assert p.intro() == 'patched intro'

Or you could set item in the instance dict:

def test_person_intro(monkeypatch):
 p = Person(name='Joe', age=20)
 monkeypatch.setitem(p.__dict__, 'intro', lambda: 'patched intro')
 assert p.intro() == 'patched intro'

The reason an instance setattr isn't working as usual is that pydantic.BaseModel overrides __setattr__ to only allow a restricted set of names. You will see the same error doing person.intro = "other" as well, it is unrelated to pytest's monkeypatch fixture.

answered Mar 21, 2023 at 17:03
Sign up to request clarification or add additional context in comments.

Comments

2

To simplify from the answer by wim, If wanting to patch manually, this worked for me:

p.__dict__['myattr'] = 'myval'

After this, p.myattr also worked.

answered Apr 27, 2023 at 15:40

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.