I'm using the Python mock module for tests. I would like to replace an active object with a mock, and automatically have all calls made to the mock object forwarded to the original object. I think this is called a "Spy" in standard testing terminology. At the moment I'm doing inside a test:
# Insert a mock replacement orig_active_attr = server.active_attr server.active_attr = mock.Mock() # Set up side effects to 'proxy' to the original object server.active_attr.meth1.side_effect = orig_active_attr.meth1 server.active_attr.meth2.side_effect = orig_active_attr.meth2 # Call the method being tested server.method_being_tested() # Assert stuff on the mock. server.active_attr.meth2.assert_called_once()
It would be nice if all method calls on the mock could be forwarded to the live object automatically without the boilerplate.
How do we mock in Python? Mocking in Python is done by using patch to hijack an API function or object creation call. When patch intercepts a call, it returns a MagicMock object by default. By setting properties on the MagicMock object, you can mock the API call to return any value you want or raise an Exception .
Mock vs. So what is the difference between them? MagicMock is a subclass of Mock . It contains all magic methods pre-created and ready to use (e.g. __str__ , __len__ , etc.). Therefore, you should use MagicMock when you need magic methods, and Mock if you don't need them.
side_effect: A function to be called whenever the Mock is called. See the side_effect attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns DEFAULT , the return value of this function is used as the return value.
I seem to have stumbled across the solution:
import mock class A(object): def meth(self, a): return a a = A() ma = mock.Mock(wraps=a)
Seems to work okay for functions, methods and properties, but not for class or instance attributes.
See the documentation.
You can use patch.object(wraps=obj_instance)
as suggested in Spying on instance methods with Python's mock module.
For example:
from mock import patch class Foo(object): def bar(self, x, y): return x + y + 1 def test_bar(): foo = Foo() with patch.object(foo, 'bar', wraps=foo.bar) as wrapped_foo: foo.bar(1, 2) wrapped_foo.assert_called_with(1, 2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With