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()?
Related
I use unittest in my testing. I import a class in yhab.main package as...
from yhab.blah import SomeClass
def some_func():
some_instance = SomeClass()
return some_instance.method()
yhab.blah.SomeClass is defined as...
class SomeClass:
def method(self):
return 'hello'
And then I write a test like this...
#mock.patch('yhab.blah.SomeClass')
def test_mock_of_blah_someclass(mock_some_class):
assert some_func() != 'hello'
the invocation of method() calls the real instance, not a mock.
But if I do this...
#mock.patch('yhab.main.SomeClass')
def test_mock_of_main_someclass(mock_some_class):
assert some_func() != 'hello'
the invocation of method() calls the mock, not the real instance and the test passes.
Why is that?
I was thinking that python must make some sort of copy of the class definition when an import happens, but I wrote a test that proves that to not be the case.
The docs say the following, which kind of eludes to this, but it doesn't really say it outright, and IMO doesn't really explain it, especially for a python newb...
Patching a class replaces the class with a MagicMock instance. If the
class is instantiated in the code under test then it will be the
return_value of the mock that will be used.
Do the docs need to be updated to be clear?
After you import SomeClass from yhab.blah, it ends up in the yhab.main namespace, not in the yhab.blah namespace.
Try to use #mock.patch('yhab.main.SomeClass') instead of #mock.patch('yhab.blah.SomeClass').
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
I have a code like this:
class A():
def __init__(self, a):
self.a = a
def outer_method(self):
def inner_method():
return self.a +1
return inner_method()
I want to write a test for inner_method. For that, I am using a code like this:
def find_nested_func(parent, child_name):
"""
Return the function named <child_name> that is defined inside
a <parent> function
Returns None if nonexistent
"""
consts = parent.__code__.co_consts
item = list(filter(lambda x:isinstance(x, CodeType) and x.co_name==child_name, consts ))[0]
return FunctionType(item, globals())
Calling it with find_nested_func(A().outer_method, 'inner_method') but it fails when calling to 'FunctionType' because the function cannot be created since 'self.a' stops existing in the moment the function stops being an inner function. I know the construction FunctionType can recive as an argument a closure that could fix this problem , but I don't know how to use it. How can I pass it?
The error it gives is the next one:
return FunctionType(item, globals())
TypeError: arg 5 (closure) must be tuple
Why are you trying to test inner_method? In most cases, you should only test parts of your public API. outer_method is part of A's public API, so test just that. inner_method is an implementation detail that can change: what if you decide to rename it? what if you refactor it slightly without modifying the externally visible behavior of outer_method? Users of the class A have no (easy) way of calling inner_method. Unit tests are usually only meant to test things that users of your class can call (I'm assuming these are for unit tests, because integration tests this granular would be strange--and the same principle would still mostly hold).
Practically, you'll have a problem extracting functions defined within another function's scope, for several reasons include variable capture. You have no way of knowing if inner_method only captures self or if outer_method performs some logic and computes some variables that inner_method uses. For example:
class A:
def outer_method():
b = 1
def inner_method():
return self.a + b
return inner_method()
Additionally, you could have control statements around the function definition, so there is no way to decide which definition is used without running outer_method. For example:
import random
class A:
def outer_method():
if random.random() < 0.5:
def inner_method():
return self.a + 1
else:
def inner_method():
return self.a + 2
return inner_method()
You can't extract inner_method here because there are two of them and you don't know which is actually used until you run outer_method.
So, just don't test inner_method.
If inner_method is truly complex enough that you want to test it in isolation (and if you do so, principled testing says you should mock out its uses, eg. its use in outer_method), then just make it a "private-ish" method on A:
class A:
def _inner_method(self):
return self.a + 1
def outer_method(self):
return self._inner_method()
Principled testing says you really shouldn't be testing underscore methods, but sometimes necessity requires it. Doing this things way allows you test _inner_method just as you would any other method. Then, when testing outer_method, you could mock it out by doing a._inner_method = Mock() (where a is the A object under test).
Also, use class A. The parens are unnecessary unless you have parent classes.
I'm trying to use python's mock.patch to implement unit tests with nose.
class A:
def setUp(self):
self.b = 8 #contrived example
#patch.object('module.class', 'function', lambda x: self.b)
def testOne(self):
# do test #
Here, patch complains that it doesnt know self (which is correct). What is best way to get this kind of functionality in a clean fashion?
I know I can use a global variable, or that I can mock it within the test (but that involves me cleaning up the objects at the end of the test).
You cannot use self on method decorator because you are in the class definition and the object doesn't exist. If you really want to access to self and not just use some static values you can consider follow approach: totest is a module in my python path and fn is the method that I would patch, moreover I'm using a fixed return_value instead a function for a more readable example
class MyTestCase(unittest.TestCase):
def setUp(self):
self.b = 8 #contrived example
def testOne(self):
with patch('totest.fn', return_value=self.b) as m:
self.assertEqual(self.b, m())
self.assertTrue(m.called)
#patch("totest.fn")
def testTwo(self,m):
m.return_value = self.b
self.assertEqual(self.b, m())
self.assertTrue(m.called)
In testOne() I use patch as a context and I will have the full access to self. In testTwo() (that is my standard way) I set up my mock m at the start of the test and then use it.
Finally I used patch() instead of patch.object() because I don't really understand why you need patch.object() but you can change it as you like.
I'm trying to set up some automatic unit testing for a project. I have some functions which, as a side effect occasionally call another function. I want to write a unit test which tests that the second function gets called but I'm stumped. Below is pseudocode example:
def a(self):
data = self.get()
if len(data) > 3500:
self.b()
# Bunch of other magic, which is easy to test.
def b(self):
serial.write("\x00\x01\x02")
How do I test that b()-gets called?
You can mock the function b using mock module and check if it was called. Here's an example:
import unittest
from mock import patch
def a(n):
if n > 10:
b()
def b():
print "test"
class MyTestCase(unittest.TestCase):
#patch('__main__.b')
def test_b_called(self, mock):
a(11)
self.assertTrue(mock.called)
#patch('__main__.b')
def test_b_not_called(self, mock):
a(10)
self.assertFalse(mock.called)
if __name__ == "__main__":
unittest.main()
Also see:
Assert that a method was called in a Python unit test
Mocking a class: Mock() or patch()?
Hope that helps.
Various solutions are possible for this thing. But first, I have to point out that unit testing is meant for testing units; what a unit is can be a matter of viewing things. In your case I'd say a unit is the function a() because you would like to test that your unit behaves correctly, meaning it calls function b() at the right spot. A different view would be to say that functions a() and b() are a unit. Then you do not like to check whether function b() gets called, you just want to test the result of the call of function a(). So make up your mind which suits your case best.
In case you really want to test function a() as a unit, you should prepare your unit to being tested. In your case that could be done by adding to it an additional argument (which defaults to function b) and which will be used instead of the hard-coded function b() call in a():
def a(self, subfunction=None):
is subfunction is None: # for testing
subfunction = self.b
data = self.get()
if len(data) > 3500:
subfunction()
Now you can inject (during testing) a helper function which just informs the test that it got called:
store = None
def injected(*args, **kwargs):
global store
store = args, kwargs
obj.a(subfunction=injected)
# now check if global store is set properly