12

I'm trying to patch a class method using mock as described in the documentation. The Mock object itself works fine, but its methods don't: For example, their attributes like call_count aren't updated, even though the method_calls attribute of the class Mock object is. More importantly, their return_value attribute is ignored:

class Lib: """In my actual program, a module that I import""" def method(self): return "real" class User: """The class I want to test""" def run(self): l = Lib() return l.method() with patch("__main__.Lib") as mock: #mock.return_value = "bla" # This works mock.method.return_value = "mock" u = User() print(u.run()) >>> mock <MagicMock name='Lib().method()' id='39868624'> 

What am I doing wrong here?

EDIT: Passing a class Mock via the constructor doesn't work either, so this is not really related to the patch function.

3 Answers 3

18

I have found my error: In order to configure the methods of my mock's instances, I have to use mock().method instead of mock.method.

class Lib: """In my actual program, a module that I import""" def method(self): return "real" class User: """The class I want to test""" def run(self): l = Lib() return l.method() with patch("__main__.Lib") as mock: #mock.return_value = "bla" # This works mock().method.return_value = "mock" u = User() print(u.run()) 
Sign up to request clarification or add additional context in comments.

2 Comments

I guess you can mark this answer as the best answer. It solved my problem too.
Your answer confused me for a moment until I understood that subsequent calls to mock() within the context manager would return the same (mock) object each time. I think to make the example a bit less confusing it should use the mock library's intended API as such: mock.return_value.method.return_value = "mock"
1
from mock import * class Lib: """In my actual program, a module that I import""" def method(self): return "real" class User: """The class I want to test""" def run(self, m): return m.method() with patch("__main__.Lib") as mock: #mock.return_value = "bla" # This works mock.method.return_value = "mock" print User().run(mock) 

2 Comments

This works but I have to pass my mock to every method that I call. Does this approach have any advantage over my own answer that I'm missing?
Passing a class Mock via the constructor doesn't work either I was still working on the solution, I figured I'd at least share part of what I'd accomplished. Btw nice job figuring it out.
1

I mock classmethods like this:

def raiser(*args, **kwargs): raise forms.ValidationError('foo') with mock.patch.object(mylib.Commands, 'my_class_method', classmethod(raiser)): response=self.admin_client.get(url, data=dict(term='+1000')) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.