Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking out methods on any instance of a python class

I want to mock out methods on any instance of some class in the production code in order to facilitate testing. Is there any library in Python which could facilitate this?

Basically, I want to do the following, but in Python (the following code is Ruby, using the Mocha library):

  def test_stubbing_an_instance_method_on_all_instances_of_a_class     Product.any_instance.stubs(:name).returns('stubbed_name')     assert_equal 'stubbed_name', SomeClassThatUsesProduct.get_new_product_name   end 

The important thing to note from above is that I need to mock it out on the class level, since I'm actually need to mock out methods on an instance created by the thing I'm testing.

Use Case:

I have a class QueryMaker which calls a method on an instance of RemoteAPI. I want to mock out the RemoteAPI.get_data_from_remote_server method to return some constant. How do I do this inside a test without having to put a special case within the RemoteAPI code to check for what environment it's running in.

Example of what I wanted in action:

# a.py class A(object):     def foo(self):         return "A's foo"  # b.py from a import A  class B(object):     def bar(self):         x = A()         return x.foo()  # test.py from a import A from b import B  def new_foo(self):     return "New foo"  A.foo = new_foo  y = B() if y.bar() == "New foo":     print "Success!" 
like image 352
Jamie Wong Avatar asked Feb 18 '11 02:02

Jamie Wong


People also ask

Can we mock a class in Python?

Once you patch a class, references to the class are completely replaced by the mock instance. mock. patch is usually used when you are testing something that creates a new instance of a class inside of the test.

What is the difference between mock and MagicMock?

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.


1 Answers

Needing to mock out methods when testing is very common and there are lots of tools to help you with it in Python. The danger with "monkey patching" classes like this is that if you don't undo it afterwards then the class has been modified for all other uses throughout your tests.

My library mock, which is one of the most popular Python mocking libraries, includes a helper called "patch" that helps you to safely patch methods or attributes on objects and classes during your tests.

The mock module is available from:

http://pypi.python.org/pypi/mock

The patch decorator can be used as a context manager or as a test decorator. You can either use it to patch out with functions yourself, or use it to automatically patch with Mock objects that are very configurable.

from a import A from b import B  from mock import patch  def new_foo(self):     return "New foo"  with patch.object(A, 'foo', new_foo):     y = B()     if y.bar() == "New foo":         print "Success!" 

This handles the unpatching for you automatically. You could get away without defining the mock function yourself:

from mock import patch  with patch.object(A, 'foo') as mock_foo:     mock_foo.return_value = "New Foo"      y = B()     if y.bar() == "New foo":         print "Success!" 
like image 53
fuzzyman Avatar answered Oct 11 '22 20:10

fuzzyman