mocking in multithreaded context - python

I would like to write some integration tests for some classes that start in multithreaded context. The problem is one of the classes has some external library which I want to mock.
Example:
Foo.py
import threading
from external_lib import function_i_want_to_mock
class Foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
print(self.run_function())
def run_function(self):
return function_i_want_to_mock()
Bar.py
import threading
from foo import Foo
class Bar(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
foo = Foo()
foo.start()
test_mock_thread.py
from unittest.mock import patch
from bar import Bar
def test_run():
with patch("foo.function_i_want_to_mock"):
bar = Bar()
bar.start()
bar.join()
if __name__ == '__main__':
test_run()
When I run this test, the function does not get mocked and it is being imported normally. Is there a way to pass the mocked version through the threads?

Related

unittest mock how to mock a method being called

I want to test that method a calls method b. These methods are in separate files, and are not a part of class object.
# file_a.py
from file_b import b
def a():
b()
# file_b.py
def b():
test
import unittest
from unittest import mock
from file_a import a
class MyTestCase(unittest.TestCase):
#mock.patch('file_b.b')
def test_b_called(self, mock):
a()
mock.assert_called()
if __name__ == "__main__":
unittest.main()
This fails with AssertionError: Expected 'b' to have been called.
Is there a right way to do this?
When you import a function into the current namespace, like in your example, the function will need to be patched in that namespace. In your case, you need:
#mock.patch('file_a.b')
You would patch file_b.b if you had done the import and use like this:
import file_b
def a():
file_b.b()

how to import classes from one module and initialise and run it in django

How to import classes from all .py in a module with same structure and run by iterating over it. For Example,
module_one:
script_a:
class A:
def __init__(self,**kwargs):
code here
def run(self,**kwargs):
code here
def finish(self,**kwargs):
code here
script_b:
class B:
def __init__(self,**kwargs):
code here
def run(self,**kwargs):
code here
def finish(self,**kwargs):
code here
and so on ...
module_two:
script:
class Run:
def run_all(self,**kwargs):
for class in classes_from_module_one:
c = class()
c.run()
c.finish()
First of all, please note that module refers to python file, while to what you refer as module is usually called a package.
Now, for your problem, you could use some mixture of utilities found in pkgutil, importlib, and inspect or simple dir(). For example, using walk_modules and get_members:
# pack/mod_a.py
class A:
def __init__(self):
pass
def run(self):
print("A run!")
def finish(self):
print("A finished!")
# pack/mod_b.py
class B:
def __init__(self):
pass
def run(self):
print("B run!")
def finish(self):
print("B finished!")
# all.py
from importlib import import_module
from inspect import getmembers
from pkgutil import iter_modules
class Run:
def run_all(self, **kwargs):
modules = iter_modules(["pack"])
for module in modules:
members = getmembers(import_module(f"pack.{module[1]}"))
my_classes = [member for name, member in members if not name.startswith("_")]
for cls in my_classes:
c = cls()
c.run()
c.finish()
if __name__ == '__main__':
run = Run()
run.run_all()
The output is:
A run!
A finished!
B run!
B finished!
However for this solution you have to note, that getmembers will return all members of module - including built-ins, and imported entities to the modules - so you will have to implement your own check to properly filter-out those unwanted (see simple startswith in my example).

Mock a Class, but not one of its functions

When I import MyApp from app.py, a instance of the SerialConnection class
is created immediately. I want to mock the SerialConnection class but I still need a function from within this SerialConnection class.
app.py
# A module that creates strings that is sent via SerialConnection
from myserial import SerialConnection
class MyApp():
global ser
ser = SerialConnection() # ---> Needs to be mocked
def __init__(self):
pass
#ser.decorator # ---> Needs to be by-passed
def myfunc(self):
return 'testing1234'
myserial.py
# A module to write and read to a serial/UART buffer
from functools import wraps
import serial
class SerialConnection():
def __init__(self):
""" Initilize the Serial instance. """
self.ser = serial.Serial(port=2, baudrate=9600)
def decorator(self, func):
#wraps(func)
def wrapper_func(*args):
return func(*args)
return wrapper_func
test_app.py
# This file tests the function "myfunc" from "MyApp" class.
from patch import mock
#patch('myserial.SerialConnection')
def test_myfunc(mock_class):
# I can now import MyApp successfuly...
from app import MyApp
# ..but I need to bypass the decorator myserial.SerialConnection.decorator
# do I add a by-pass decorator to the "mock_class"?
# myfunc() turns out to be mocked and not a real function
assert MyApp().myfunc() == 'testing1234'

Python 3 unittest cannot mock method used inside functions

I am trying unit test in Python.
test.py
from unittest import TestCase,main
from unittest.mock import patch
import file
def mock_return(*args):
return -1
class Tests(TestCase):
#patch("file.Foo.a", side_effect=mock_return)
def test_1(self, mock_fun):
self.assertEqual(file.Foo().a(), -1)
#patch("os.urandom", side_effect=mock_return)
def test_2(self, mock_fun):
self.assertEqual(file.Foo().b(), -1)
if __name__ == "__main__":
main()
file.py
from os import urandom
class Foo:
def a(self):
return 1
def b(self):
return urandom(1)
Why test_1 passed but test_2 failed? Is there a way to mock a method used by other class?
You must patch the binding used by the function being tested.
from os import urandom # in file.py
binds name urandom to the function os.urandom in the file module. Foo.b accesses the function via the file.urandom binding. So the test for Foo.b must patch file.urandom, not os.urandom.

unittest, running test from other file

I can't seem to get the Test1.test_something() in test2 to work.. not sure if it's because they are both inheriting from the same base?
Helper.py:
class baseTest(unittest.TestCase):
def setUp(self, param="Something"):
print param
pass
Test1.py
from Helper import baseTest
class test1(baseTest):
def setUp(self):
super(test1, self).setUp('foo')
def test_something(self):
assert 1 == 1, "One does not equal one."
Test2.py
from Helper import baseTest
import Test1
class test2(baseTest):
def setUp(self):
super(test2, self).setUp('bar')
def test_something(self):
Test1.test_somehing()
Now, I had this working previously, when I had the setUp for test1 and test2 within their classes, but once I had them both inherit from baseTest, I started getting a unbound method <method> must be called with Test instance as first argument (got nothing instead). Any suggestions?
The problem is that Test1.test_something() is an instance method, not a class method. So you can't just call it like that (besides, even if it is class method, it should have been Test1.test1.test_something).
One way to do it (without messing around with the unittest.TestCase mechanism):
Test2.py
import Test1
class test2(Test1.test1):
# whatever else
And you're done, test2 inherits Test1.test1.test_something() automatically. If you need your test2's test_something to do extra stuff, just do super(test2, self).test_something() within your overridden definition of test_something in test2 class.
Move the tests that are shared by both Test1 and Test2 classes into BaseTest:
test.py:
import unittest
import sys
class BaseTest(unittest.TestCase):
def setUp(self, param="Something"):
print param
pass
def test_something(self):
assert 1 == 1, "One does not equal one."
class Test1(BaseTest):
def setUp(self):
super(Test1, self).setUp('foo')
test2.py:
import test
import unittest
import sys
class Test2(test.BaseTest):
def setUp(self):
super(Test2, self).setUp('bar')

Categories