Using patch to to mock a function (as opposed to a method) - python

I want to do something like the following example (found here)
>>> with patch.object(ProductionClass, 'method', return_value=None) as mock_method:
... thing = ProductionClass()
... thing.method(1, 2, 3)
However this is patching the method called method on ProductionClass. I want to patch a generic function within a context. Ideally something looking like...
with path.something(my_fn, return_value=my_return) as mock_function:
do_some_other_fn()
my_fn is called deep within do_some_other_fn and therefore is difficult to mock out directly. This seems like it should be straight forward but I can't find the right syntax
EDIT In the module that do_some_other_fn lives I import my_fn like followings
from my_module import my_fn
So I need a way to be able to tell mock to patch that from outside the module. Is this possible?
EDIT 2 I think this makes it more clear what I am looking for
This works but is not ideal:
import my_module
with patch('my_module.fn', return_value='hello') as patch_context:
x = my_module.fn()
# x now contains 'hello'
However I would much rather have it work like this (or something similar)
from my_module import fn
with patch('my_module.fn', return_value='hello') as patch_context:
x = fn()
# x contains real result from real call to fn()

Your attempt to patch with from my_module import fn does not work because the import statement creates a local symbol fn which points to whatever value fn has in my_module at the time of import. You later patch my_module.fn but it does not matter because you already have a local copy of fn.
If the file that contains the patch call is the main module (the file that python initially loaded), you should be able to do it by patching __main__.fn:
from my_module import fn
with patch('__main__.fn', return_value='hello') as patch_context:
x = fn()
If the file that contains the patch call is loaded as a module from the main module then __main__ won't work and you need to pass the absolute module name of the module that contains your patch call to patch rather than __main__.

You can see function like module object's static method. To patch a function func in module mymodule you can use
patch("mymodule.func", return_value=my_return)
You should take care of Where to patch and if the function is in the same module where you have the test should use "__main__.func" as patch argument.
patch like patch.object can be useed as decorator, context or by start() and stop() method.
Now when in a module you import a function from an other module like:
from mymodule import func as foo
You create a new reference to func in the new module called foo. Every
time in this module you call foo you will use the reference to mymodule.func that you load when you imported it: if you whould like change this behavior you should patch foo in the new module.
To make it more clear I build an example where you have mymodule that contain func, module_a that include mymodule and use mymodule.func, module_b that use from mymodule import func as foo and use bot foo and mymodule.func
mymodule.py
def func():
return "orig"
module_a.py
import mymodule
def a():
return mymodule.func()
module_b.py
from mymodule import func as foo
import mymodule
def b_foo():
return foo()
def b():
return mymodule.func()
test.py
import unittest
from unittest.mock import *
import mymodule
import module_a
import module_b
class Test(unittest.TestCase):
def test_direct(self):
self.assertEqual(mymodule.func(), "orig")
with patch("mymodule.func", return_value="patched"):
self.assertEqual(mymodule.func(), "patched")
def test_module_a(self):
self.assertEqual(module_a.a(), "orig")
with patch("mymodule.func", return_value="patched"):
self.assertEqual(module_a.a(), "patched")
def test_module_b(self):
self.assertEqual(module_b.b(), "orig")
with patch("mymodule.func", return_value="patched"):
self.assertEqual(module_b.b(), "patched")
self.assertEqual(module_b.b_foo(), "orig")
with patch("module_b.foo", return_value="patched"):
self.assertEqual(module_b.b(), "orig")
self.assertEqual(module_b.b_foo(), "patched")
if __name__ == '__main__':
unittest.main()
In other words what really rules on choosing where to patch is how the function is referenced where you want use the patched version.

Related

Mocking function that is implicitly imported into a module

I would like to mock a function inside a module, however, this function is not explicitly imported. Consider following scenario.
helper_functions.py
def foo_1():
...
def foo_2():
...
helper_functions = [foo1, foo2]
my_module
from helper_functions import helper_functions
def do_something(foo):
...
some_results = [do_something(foo) for foo in helper_functions]
I need to patch ONLY foo2 but in my_module, because I'm basically testing how do_something works.
When I try this
from unittest import patch
#patch('my_module.foo2')
def test_do_something():
...
I get an obvious error saying that foo2 does not exist in the namespace of my_module.
Can I bypass it somehow?

Python pass variable to imported module at "compilation" time

I'm trying to create an object from a custom class with a decorator in it.
Then I need to use the decorator of that object to create a bunch of functions in a different file.
I found the solution of using builtins online but it feels a bit hacky and makes my lsp spit out a bunch of errors.
I'm wondering if anyone knows a better solution.
This is my file structure:
main.py
mylib
├── A.py
└── B.py
main.py
import builtins
from mylib.A import A
a = A("This is printing in the decorator")
builtins.FOO = a
import mylib.B as B
B.foo()
B.poo()
A.py
class A:
def __init__(self, _message):
self.message = _message
def our_decorator(self, func):
def function_wrapper():
print(self.message)
func()
return function_wrapper
B.py
import builtins
#builtins.FOO.our_decorator
def foo():
print("foo")
#builtins.FOO.our_decorator
def poo():
print("poo")
I don't want to change the file structure if it can be avoided.
Using builtins to have a magically created decorator is indeed hacky.
An alternative would be to patch the functions in B from main. It is slightly cleaner (and linters should not complain) because the B module has no longer to be aware of the decorator:
main.py:
from mylib.A import A
a = A()
import mylib.B as B
# decorate here the functions of the B module
B.foo = a.our_decorator(B.foo)
B.poo = a.our_decorator(B.poo)
B.foo()
B.poo()
A.py is unchanged...
B.py:
def foo():
print("foo")
def poo():
print("poo")
As only one version of a module exists in a process, you can even use the functions of B from a third module, provided:
either it is imported after the decoration
or it only imports the module name (import mylib.B as B) and not directly the functions (from mylib.B import foo)

Avoid duplicate name when importing a sub-module with only one public member from a package

Basic Setup
Suppose I want to create a class named Foo. I may create a file like so:
foo.py:
class Foo:
def __init__(self):
self.data = "world"
def print(self):
print("Hello, " + self.data)
To utilize this class in my main script:
main.py
import foo
test = foo.Foo()
test.print()
Having to type foo.Foo() every time I instantiate the class already feels ridiculous enough, but it gets worse when I want to organize my code by separating my classes into a package:
classes/__init__.py
# Empty
classes/foo.py
# Copy of foo.py, above
main.py
import classes.foo
test = classes.foo.Foo()
test.print()
Simple Answer
I know I can clean this up somewhat by using from X import Y like so:
from classes.foo import Foo
test = Foo()
Preferred Answer
Because the file foo.py contains only one member whose name matches the file, I would prefer if I could do something like the following:
from classes import Foo
# Or:
import classes.Foo as Foo
test = Foo()
Is there a way to do this? Maybe with some code in my __init__.py?
In classes/__init__.py, put:
from .foo import Foo
Now you can write from classes import Foo.

Patch over a function imported inside another function

In order to avoid a circular import, I've been forced to define a function that looks like:
# do_something.py
def do_it():
from .helpers import do_it_helper
# do stuff
Now I'd like to be able to test this function, with do_it_helper patched over. If the import were a top level import,
class Test_do_it(unittest.TestCase):
def test_do_it(self):
with patch('do_something.do_it_helper') as helper_mock:
helper_mock.return_value = 12
# test things
would work fine. However, the code above gives me:
AttributeError: <module 'do_something'> does not have the attribute 'do_it_helper'
On a whim, I also tried changing the patch statement to:
with patch('do_something.do_it.do_it_helper') as helper_mock:
But that produced a similar error. Is there any way to mock this function, given the fact that I'm forced into importing it within the function where it's used?
You should mock out helpers.do_it_helper:
class Test_do_it(unittest.TestCase):
def test_do_it(self):
with patch('helpers.do_it_helper') as helper_mock:
helper_mock.return_value = 12
# test things
Here's an example using mock on os.getcwd():
import unittest
from mock import patch
def get_cwd():
from os import getcwd
return getcwd()
class MyTestCase(unittest.TestCase):
#patch('os.getcwd')
def test_mocked(self, mock_function):
mock_function.return_value = 'test'
self.assertEqual(get_cwd(), 'test')

Python: Mocking a module that's being used by a module I'm testing

I would like to mock a certain module in order to test a piece of code that is using the module.
That is to say, I have a module my_module which I'd like to test. my_module imports an external module real_thing and calls real_thing.compute_something():
#my_module
import real_thing
def my_function():
return real_thing.compute_something()
I need to mock real_thing so that in a test it will behave like fake_thing, a module that I've created:
#fake_thing
def compute_something():
return fake_value
The test calls my_module.my_function() which calls real_thing.compute_something():
#test_my_module
import my_module
def test_my_function():
assert_something(my_module.my_function())
What should I add to the test code so that my_function() will call fake_thing.compute_something() within the test instead of real_thing.compute_something()?
I was trying to figure out how to do so with Mock, but I haven't.
Simply that no ? Hack the sys.modules
#fake_thing.py
def compute_something():
return 'fake_value'
#real_thing.py
def compute_something():
return 'real_value'
#my_module.py
import real_thing
def my_function():
return real_thing.compute_something()
#test_my_module.py
import sys
def test_my_function():
import fake_thing
sys.modules['real_thing'] = fake_thing
import my_module
print my_module.my_function()
test_my_function()
Outputs : 'fake_value'
http://code.google.com/p/mockito-python/
>>> from mockito import *
>>> dog = mock()
>>> when(dog).bark().thenReturn("wuff")
>>> dog.bark()
'wuff'
http://technogeek.org/python-module.html - how to replace ,load module dynamically

Categories

Resources