I have taken a below code from a large code repository of interdependent modules. I want to run this as an independent unit for testing.
In below while calling db_obj.create_connection() i have to pass the value of debug_obj which means I have to import all the dependent implementation of that which I do not want.
However, if I pass None as db_obj.create_connection(None) then it will fail at debug_obj.info('inside create_connection') due to attribute error. Unless I go and disable debug_obj.info() wherever used.
What could be the best possible way to handle such a situation where you wanted to disable you dependent library codes just for your unit testing without commenting its callings.
import pyodbc
class DBOperations(object):
def __init__(self,db_params):
self.db_params=db_params
def create_connection(self, debug_obj):
debug_obj.info('inside create_connection')
mycode_to_run_create_connection
if __name__ == '__main__':
db_obj = DBOperations(db_params ='param_for_db_connection')
db_obj.create_connection(None)
It looks like using the mock library would be a good way of dealing with a situation like yours.
In your case, a Mock or MagicMock should do the trick.
In the same place where you are instantiating the DBOperations class, you could mock the debug_obj:
from unittest.mock import Mock
...
...
if __name__ == '__main__':
debug_obj = Mock()
db_obj = DBOperations(db_params ='param_for_db_connection')
db_obj.create_connection(debug_obj)
Once the Mock object has been instantiated, attributes can be assigned to it, for example:
debug_obj = Mock()
debug.info = print
debug.info('test')
# >>> prints the word test to the stdout
Related
I am trying to implement unittests for my python program. The problem is, that my program is using several imported classes, which I would like to replace by a mocked object/class to verify single functions/methods.
I do not get any errors with my mocked class. But it appears that the mock itself didn't replace the object I wanted to replace.
This is basically my structure:
First the class I want to mock. Might look like that:
class ToMock():
def getSomething(self):
return "something"
The class I want to test looks like this:
from x.y import ToMock
class ClassToTest():
def __init__(self):
self.obj = ToMock()
def returnStuff():
return self.obj.getSomething()
As you can imagine, I want to test the returnStuff method. Therfore I want to mock .getSomething, or better said the whole ToMock object.
The unittest should therefore test the ClassToTest with the mocked ToMock class. I tried several mock.patch variants, but I couldn't get it to run/test properly.
import unittest
from unittest import mock
from a.b import ClassToTest
class TestObject(unittest.TestCase):
def setUp(self):
with mock.patch('x.y.ToMock') as mock_obj:
mock_obj.return_value.getSomething().return_value="mocked return value"
self.test_class = ClassToTest()
result = self.test_class.returnStuff() # This should return now 'mocked return value', I guess?
mock_obj.return_value.getSomething.assert_called_once_with("")
The problem I face is, that the self.test_class.returnStuff() is not "calling" the mocked object, but imports the real class etc. and therefore I am running into timeouts, or similar stuff.
I am sure, that I provide the wrong path for the object which should be mocked. Perhaps someone can hint me into the right direction.
Thanks
-GreNait
The issue is that you are not patching in the correct place. You are patching where the object is defined as opposed to where it is looked up.
a.py
-> Defines ToMock
b.py
-> from a import ToMock
-> some_function/class instantiates ToMock
In your code shown you are patching a.ToMock however you should be patching b.ToMock. That is why it is not running your mock object when testing. You can read more about where to patch here.
I'm trying to create some unitary tests for a method that needs to instantiate some objects using classes from external modules that I don't want to use, as they need arguments that I can't pass at object initialization.
For example, imagine that the code I want to test has the following structure:
from module_one import Class_1
from module_two import Class_2
class MyMainClass()
def method_to_be_tested(self, stuff):
var_one = Class_1(stuff.data)
self.var_two = Class_2(var_one.data)
print("The var is %s" % self.var_two.attribute)
stuff is a complex argument, with several attributes that I can't mock.
This is what I have tried in my test method, using patch from unittest.mock (but it didn't work):
#patch('module_two.Class_2')
#patch('module_one.Class_1')
def test_method(self, mocked_class1, mocked_class2):
stuff = mock()
mocked_class1.return_value = 'some_stuff_that_i_dont_want'
mock_class2 = mock()
mock_class2.attribute = 'what_i_want_to_get'
mocked_class2 = mock_class2
mymainclass.method_to_be_tested(stuff)
assertEqual('what_i_want_to_get', mymainclass.var_two.attribute)
It seems that the patch or something isn't working, as it throws an error telling me that str object has no attribute data, referring to var_one when var_one.data is used as an argument for Class2.
What I want is to pass any argument to Class2 and get always what I defined in mock_class2.
Edit: mock() is imported from mockito module, but maybe I don't need this to achieve what I need.
You can certainly do that without mockito. Assuming that MyMainClass is defined in module mainmodule:
import unittest.mock as mock
class TestMyMainClass(unittest.TestCase):
#mock.patch('mainmodule.Class_2')
#mock.patch('mainmodule.Class_1')
def test_method(self, mocked_class1, mocked_class2):
stuff = mock.Mock()
mocked_class2_instance = mock.Mock()
mocked_class2_instance.attribute = 'what_i_want_to_get'
mocked_class2.return_value = mocked_class2_instance
mymainclass = MyMainClass()
mymainclass.method_to_be_tested(stuff)
self.assertEqual('what_i_want_to_get', mymainclass.var_two.attribute)
if __name__ == '__main__':
unittest.main()
Now if you think this test sucks, I have to agree.
You have to patch Class_1, yet it doesn't even appear in the test.
It is not obvious why Class_2 is relevant at all unless you are familiar with the internal implementation details of the method under test. Actually you are testing implementation details instead of (or in addition to) observable behavior, which is usually bad.
The behavior of the method depends (hopefully) on stuff.data but the test ignores that and will happily pass whatever it is. An yet you need a stuff object with a data attribute even if you don't care about what it is.
The main problem here is that by instantiating Class_1 and Class_2 inside the method you are tightly coupling the three pieces of code but now you want to test them in isolation. That's going to be hard and will probably lead to fragile and hard to read tests.
If you really want your code to be like that I suggest you test the method without mocking neither Class_1 nor Class_2. Now if you say you don't want to do that because stuff (or better, stuff.data; why are you passing the whole think when you only need the data?) is hard to mock or instantiate, I would guess that there is a problem with your design, but that is as far as I can get from your contrived example.
I'm trying to mock out the return value of a dependent method but the return value is different between using the return_value and adding an additional argument to the mock.patch. Please help me figure out why. I tried searching online but couldn't find an answer to this.
library/abc.py:
from tools.operating_system import os_name
class ABC(object):
def get_os_info(self):
return os_name()
tools/operating_system.py:
import os
def os_name():
return os.name
library/test_abc.py:
from unittest import TestCase, mock
from library.abc import ABC
class TestMain(TestCase):
# This works because the name method returns `test`
def test_mocking_os_name(self):
with mock.patch('tools.operating_system.os.name', 'test'):
abc = ABC()
res = abc.get_os_info()
self.assertEqual(res, 'test')
# The test fails because the name method returns `<MagicMock name='name' id='4515046400'>`
def test_mocking_os_name(self):
with mock.patch('tools.operating_system.os.name') as mock_name:
mock_name.return_value = 'test'
abc = ABC()
res = abc.get_os_info()
self.assertEqual(res, 'test')
Note: This example is somewhat contrived because I could mock the os_name method. That is not the main concern. I'm trying to learn python test mocking and I want to be able to mock os.name. Thanks! This is for Python 3.7.2 but I have the same problem with Python 2.7.15
See the documentation for mock.patch: when you call this
with mock.patch('tools.operating_system.os.name', 'test')
you're doing this:
with mock.patch('tools.operating_system.os.name', NEW='test')
You're replacing os.name with the string test, so that works as you'd expect.
When you call this
with mock.patch('tools.operating_system.os.name') as mock_name:
you're doing this:
with mock.patch('tools.operating_system.os.name', NEW=DEFAULT) as mock_name:
You're leaving NEW as NEW=DEFAULT so os.name is set to MagicMock object (as the documentation says). Setting mock_name.return_value='test' does not work, because you're not calling the function os.name() anywhere in your code, and of course you should not be, because os.name is a string and not a function.
Like you said, in real code you would want to be patching os_name function instead of os.name:
def test_patching_os_name(self):
with mock.patch('library.abc.os_name') as mock_os_name:
mock_os_name.return_value = 'test'
abc = ABC()
res = abc.get_os_info()
self.assertEqual(res, 'test')
This test is not depending on the internal implementation of os_name function. If the correct behaviour of ABC class depended on os_name always returning os.name (which is what the tests are asserting), then the class could just as well use os.name itself and not depend on tools.operating_system at all.
A little personal preference for the end: I prefer injecting dependencies instead of patching whenever possible, see, for example, the article "Every mock.patch() is a little smell".
in the case of unit testing a wrapper library, testing the wrapper without depending/exercising the upstream library is a goal; In a known case, all calls to the upstream library can be mocked and that's what I've done, but I've been frustrated by changes to the wrapper that introduce more calls to the upstream library being missed by the mock tools;
How can I best fail any test that tries to use a given namespace?
My idea currently is to change all the unittest methods to have a monkey patch like
#unittest.mock.patch('wrapper_namespace.upsteam_namespace')
and reply the upstream library with a mock that can be asserted untouched; I'm hoping for an option that works globally, so that I
don't have to add a monkeypatch to every test method, though this level of granularity is acceptable; but also don't have to perform the assertion that the mock was never used in the test methods (or make a decorator to do all that either)
prohibits access to the upstream library from any part of the software
(e.g, Wrapper calls B calls Upstream, B's call to upstream might not be caught)
You don't have to patch every test method. You can easily patch over the class if you're using unittest, or just assign the module to whatever you want to patch over it with. Here's a workable example:
A fake lib in some_lib.py:
def some_lib_func():
raise ValueError("I've been called.")
def some_other_lib_func():
raise ValueError("I've been called.")
class SomeClass:
def __init__(self):
raise ValueError("I've been constructed.")
wrapper.py:
import some_lib
def wrapper1():
some_lib.some_lib_func()
def wrapper2():
some_lib.some_other_lib_func()
def wrapper3():
x = some_lib.SomeClass()
test.py:
from unittest.mock import patch, MagicMock
import unittest
import wrapper
# Alternative:
# wrapper.some_lib = MagicMock()
# Can patch an entire class
#patch('wrapper.some_lib', MagicMock())
class TestWrapper(unittest.TestCase):
def test_wrapper1(self):
wrapper.wrapper1()
def test_wrapper2(self):
wrapper.wrapper2()
def test_wrapper3(self):
wrapper.wrapper3()
if __name__ == "__main__":
unittest.main()
We would explode if the functions/classes in some_lib were called, but they aren't:
Matthews-MacBook-Pro:stackoverflow matt$ python test.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s
OK
Feel free to comment out the patch and comment in wrapper.some_lib = MagicMock(). You'll get the same result in this toy example, but there is a major difference between the two approaches:
When using #patch('wrapper.some_lib', MagicMock()) the patch is only live for that Test Case class.
When using wrapper.some_lib = MagicMock(), however, that patch will stay live for the entire length of your python program, unless you save off the original module and patch it back manually at some point. Everything that is using the wrapper module will get the mocked version.
So you could so something like:
original_lib = wrapper.some_lib
wrapper.some_lib = MagicMock()
...
# call some test suite, every call to the wrapper module will be mocked out
...
wrapper.some_lib = original_lib
...
# call some other test suite that actually needs the real thing
...
HTH.
EDIT: Misread your question slightly, but you can inspect MagicMock objects to see if they've been called, and if so, fail the test. Or just patch over with something that fails when called (instead of MagicMock). I can provide code to do this if requested (just leave a comment), but hopefully the above can get you started. I think the crux of the question was really about the global patching. Cheers!
I am trying to get a hang of mocking objects, and seem to by confused by something very basic. I am trying to mock object MyClass and then unit test one of its methods. here is my code:
import mock
import unittest
class MyClass(object):
def __init__(self, a):
self.a = a
def add_two(self):
return self.a + 2
class TestMyClass(unittest.TestCase):
#mock.patch('__main__.MyClass')
def test_add_two(self, dummy_mock):
m_my_class = mock.Mock()
m_my_class.a = 10
result = m_my_class.add_two() # I would expect the result to be 12
import ipdb;ipdb.set_trace()
self.assert_equal(result, 12)
if __name__ == '__main__':
unittest.main()
In m_my_class.a = 10 I set value of a to to and then in m_my_class.add_two() I add a two, shouldn't I get 12? However, result is:
16 import ipdb;ipdb.set_trace()
---> 17 self.assert_equal(result, 12)
18
ipdb> result
<Mock name='mock.add_two()' id='18379792'>
What am I missing?
Since I am passing the location of the class via decorator to the test method #mock.patch('__main__.MyClass'), shouldn't mocked have all the methods? Because if not, then why does it matter what class we include in the decorator?
Edit:
When I run this code, I still get the same thing.
class TestMyClass(unittest.TestCase):
#mock.patch('__main__.MyClass')
def test_add_two(self, dummy_mock):
dummy_mock.a = 10
result = dummy_mock.add_two()
import ipdb;ipdb.set_trace()
self.assert_equal(result, 12)
Result:
ipdb> result
<MagicMock name='MyClass.add_two()' id='38647312'>
Patching the class is almost certainly not what you want to do here. For example, if you changed your test method to this:
class TestMyClass(unittest.TestCase):
#mock.patch('__main__.MyClass')
def test_add_two(self, dummy_mock):
m_my_class = MyClass(5)
print m_my_class
You will find that rather than getting what you expect:
<__main__.MyClass object at 0x0000000002C53E48>
You'll get this:
<MagicMock name='MyClass()' id='46477888'>
Patching the class in the method means that any time within the method that something tries to instantiate the class it will instead get a mock object. In your particular case, calling MyClass(5) will return the same mock object as calling dummy_mock would. This allows you to set up the mock object so that when you go to test your code the mock object will behave as you want it to.
You really would only use this for dependencies, not the class you are testing. So for example, if your class retrieved data from SQL, you'd patch the SQL class to give your class a mock instead of the normal SQL connection. This allows you to test a class in isolation, without having to worry about externals (like the SQL) getting in the way.
In your example though, you seem to be trying to test a method in isolation. A way you could do that is to extract the function from the method and use that. In code:
def test_add_two(self):
test_mock = mock.Mock()
test_mock.add_two = MyClass.add_two.__func__
test_mock.a = 10
result = test_mock.add_two(test_mock)
self.assert_equal(result, 12)
Normally you wouldn't have to pass in an argument for the self argument, but as here we've pulled out the function you do need to pass in the self argument. If you want you can turn the function into a method bound to your mock object, like this:
import types
...
test_mock.add_two = types.MethodType(MyClass.add_two.__func__, test_mock, test_mock.__class__)
result = test_mock.add_two()
If the function you are testing calls any other methods, you'll need to either do this or mock it out for each of the methods.
I would advise against using this strategy too much, in part because of needing to take care of methods that the tested method calls. Of course, being able to mock out the methods it depends on may be exactly what you're trying to do. In any case, it requires the unit tests to have a pretty deep understanding of how the method works, and not just of what it is supposed to produce. That makes the test very fragile, making it so that you are likely to see the test break far more often than the method you are testing.
Why are you mocking your SUT? This is generally something that you should avoid doing because it introduces the risk that you will not be testing what you think you're testing.
The point of a unit test is to verify the behavior of a unit in complete isolation. One unit typically collaborates with other units in order to provide some useful functionality. Test doubles (mocks, fakes, etc.) are the tools used to achieve this isolation. In a unit test, collaborators of the SUT are replaced with test doubles in order to minimize the number of moving parts.
Your SUT, MyClass, doesn't appear to have any collaborators. As such, no test doubles are necessary to test this unit in isolation (it's already self-contained). This allows you to greatly simplify your unit test:
import mock
import unittest
class MyClass(object):
def __init__(self, a):
self.a = a
def add_two(self):
return self.a + 2
class TestMyClass(unittest.TestCase):
def test_add_two(self):
m_my_class = MyClass()
m_my_class.a = 10
result = m_my_class.add_two() # I would expect the result to be 12
import ipdb;ipdb.set_trace()
self.assert_equal(result, 12)
if __name__ == '__main__':
unittest.main()
Edit: The following code demonstrates how a mock object might be used. (Disclaimer: I don't normally work in Python, so my code is probably not very idiomatic. Hopefully the core point still makes sense, though.)
In this example, MyClass adds a value provided by a collaborator, instead of a hardcore value (2).
import mock
import unittest
class MyClass(object):
def __init__(self, a, get_value):
self.a = a
self.get_value = get_value
def add_value(self):
return self.a + self.get_value()
class TestMyClass(unittest.TestCase):
def test_add_value(self):
m_test_value = 42
m_test_a = 10
m_my_class = MyClass()
m_get_test_value = mock.Mock(return_value=m_test_value)
m_my_class.a = test_a
result = m_my_class.add_value()
import ipdb;ipdb.set_trace()
self.assert_equal(result, m_test_a + m_test_value)
if __name__ == '__main__':
unittest.main()
The above example uses a mock object, instead of patching a class. Here is a pretty good explanation of the difference:
Mocking a class: Mock() or patch()?