Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python mock patch a function called by another function

def f1():     return 10, True  def f2():     num, stat = f1()     return 2*num, stat 

How do I use python's mock library to patch f1() and return a custom result so I could test f2()?

Edited: Is there something wrong with my test? This doesn't seem to be working, all the tests failed with AssertionError

from foo.bar import f2 from mock import patch  class MyTest(TestCase):      def test_f2_1(self):         with patch('project.module.f1') as some_func:             some_func.return_value = (20, False)             num, stat = f2()             self.assertEqual((num, stat), (40, False))     @patch('project.module.f1')    def test_f2_2(self, some_func):        some_func.return_value = (20, False)        num, stat = f2()        self.assertEqual((num, stat), (40, False)) 
like image 721
Nam Ngo Avatar asked Apr 23 '12 08:04

Nam Ngo


People also ask

How do you mock a function called another function?

There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.

Can you mock a function in Python?

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 .

What is Side_effect in mock Python?

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.

What does @patch do in Python?

This, along with its subclasses, will meet most Python mocking needs that you will face in your tests. The library also provides a function, called patch() , which replaces the real objects in your code with Mock instances.


2 Answers

First example suggests that f1() and f2() defined in the same module. Hence the following should work:

from foo.bar import f2 from mock import patch  class MyTest(TestCase):      @patch('foo.bar.f1')     def test_f2_2(self, some_func):         some_func.return_value = (20, False)         num, stat = f2()         self.assertEqual((num, stat), (40, False)) 

Patch is on the same as import: @patch('foo.bar.f1')

Here is a good answer on the issue:

http://bhfsteve.blogspot.nl/2012/06/patching-tip-using-mocks-in-python-unit.html

like image 154
Vasiliy Avatar answered Sep 24 '22 10:09

Vasiliy


Assuming that you're using this mock libary:

def f1():     return 10, True  def f2():     num, stat = f1()     return 2*num, stat  import mock  print f2()   # Unchanged f1 -> prints (20, True)  with mock.patch('__main__.f1') as MockClass:       # replace f1 with MockClass      MockClass.return_value = (30, True)     # Change the return value      print f2()     # f2 with changed f1 -> prints (60, True) 

If your code is divided into modules you would probably need to replace __main__.f1 with the path to your module/function.

like image 41
Mariusz Jamro Avatar answered Sep 24 '22 10:09

Mariusz Jamro