Skip to main content

Know where to patch!!!

Have you tried to patch a function call in your unit test and wondering why the hell patching is not working, value I'm returning from the patched function is not the value being used in the function call. Well, may be you are not patching at the right place.

I saw this problem at work. I'll try to explain with a simple example.

you have a module module_a which has a function greet. There is another module module_b which uses this function from module_a in another function - sayHi. When we write test case for module_b's sayHi, we want to patch function call to module_a's greet method.

module_a.py
def greet():
""" returns sum of two numbers"""
return 'hello world'

module_b.py
from module_a import greet

class myClass():
def sayHi(self):
return greet()

if __name__ == '__main__':
res = myClass().sayHi()
print(res)

test_mod_b.py
import unittest
from unittest.mock import patch
from module_b import myClass
class mocktest(unittest.TestCase):
def test1(self):
with patch('module_a.greet',return_value='how are you'):
res = myClass().sayHi()
self.assertEqual(res,'how are you')

if __name__ == '__main__':
unittest.main()


 Here, we are writing test case for module_b's sayHi function and want to patch module_a's greet function. On executing this test case, it fails.

PS D:\development\test> python -m unittest
F
======================================================================
FAIL: test1 (test_ut.mocktest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:\development\test\test_ut.py", line 8, in test1
    self.assertEqual(res,'how are you')
AssertionError: 'hello world' != 'how are you'
- hello world
+ how are you


----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (failures=1)

 
Reason being  - we are patching module_a's greet function. when module_b is loaded, it first loads module_a.greet and then this function is already available in module_b. So the call will not be module_a.greet instead it will be just greet from module_b. Hence we need to patch module_b.greet .

modified unit test

import unittest
from unittest.mock import patch
from module_b import myClass
class mocktest(unittest.TestCase):
def test1(self):
with patch('module_b.greet',return_value='how are you'):
res = myClass().sayHi()
self.assertEqual(res,'how are you')

if __name__ == '__main__':
unittest.main()

unit test result - 

PS D:\development\test> python -m unittest
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK


Visual studio code showing during module_b load that greet is available as a local variable and no longer a call to module_a.greet

on the other hand, if you only import module_a in module_b then when calling greet function, you will have to refer to it as module_a.greet . In that case, this approach will not work and you need to patch module_a.greet in your unit test since you will be accessing greet function using module_a reference .



modified module_b(importing module_a and not the greet  function)

import module_a

class myClass():
def sayHi(self):
return module_a.greet()

if __name__ == '__main__':
res = myClass().sayHi()
print(res)



 updated unit test 

import unittest
from unittest.mock import patch
from module_b import myClass
class mocktest(unittest.TestCase):
def test1(self):
with patch('module_a.greet',return_value='how are you'):
res = myClass().sayHi()
self.assertEqual(res,'how are you')

if __name__ == '__main__':
unittest.main()

 PS D:\development\test> python -m unittest
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK


That's it on unit testing for now .

 

Comments

Popular posts from this blog

The view or its master was not found or no view engine supports the searched locations!!!

On an MVC application, if you are getting error " The view or its master was not found or no view engine supports the searched locations " and you see that this view (.cshtml file)is already present under the correct folder structure and every thing is correct and you have also tried a lot of posts on SO on how to fix that and that hasn't helped,  just check the build action for this file and make sure that it is set to "content". I have seen the build action set to None (by mistake)and after you deploy/publish  the application, that view would be missing  and you get this error .

Top Tweets

FSharp (5th Sept 2013) when I search for F# tweets , there are so many duplicate tweets and people are having conversation with F# hashtag. I'm not really interested in conversation , but want to check what cool stuff has been shared about F#. so wrote a simple script which searches twitter for F# hashtag, removes duplicate tweets and tweets having conversation. Here is the result- New F# Cheatsheet in PDF and HTML format using FSharp.Formatting tool http://t.co/iczl1Ge3Hz #fsharp F# Snippet: Missile Command playable in tsunami.io http://t.co/BiLQxCykJa #fsharp Building a game in a day with #fsharp & #monogame slides & code samples: http://t.co/8eX64NsqOl #fsharp #mongodb provider meetup w/ @visemet starting in 15 minutes or so - you can join us online here. https://t.co/o8egTRDAn7 Awesome custom #fsharp query support for #mongodb by @visemet! http://t.co/hJQDNhyNSt #fsharp #mongodb provider meetup w/ @visemet starting in 15 minutes or so -