73
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))
0

2 Answers 2

64

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

from foo.bar import f2
from unittest.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

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for recommending the bhfsteve.blogspot.nl link about patching and import styles. That solved one of my problems.
How would this be different if f1 and f2 were in different modules?
@HenryWoody: I believe no difference because it won't change the line @patch('foo.bar.f1') even if f1 is defined from another module because foo.bar has to imported f1 to use and we patch the imported one, not where it was defined.
32

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.

4 Comments

Would it make any difference if f1() accepts args? E.g: f1(arg)
The mocking function can be called with any number of arguments, it'll always return the return_value.
Thanks a lot @Secator. I have updated my question with a test case and it doesn't seem to be passing. What am I doing wrong?
The test failed with AssertionError

Your Answer

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.