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.
Related
I am testing a class that needs a mock in the constructor, so I usually do this:
class TestActionManager(unittest.TestCase):
#patch('actionlib.SimpleActionClient', return_value=create_autospec(actionlib.SimpleActionClient))
def setUp(self, mock1):
self.action_manager = ActionManager()
Then in this class I add all the tests. So the first one is working fine
def test_1(self):
self.action_manager.f()
self.action_manager.f.assert_called_once()
But if I add another test and run both
def test_2(self):
self.action_manager.f()
self.action_manager.f.assert_called_once()
It says f has been called twice. I was expecting setUp to create a new ActionManager (and hence create a new mock) before starting every test, but it is clearly not happening, since the mock is somehow shared. Also I tried to do
def tearDown(self):
del self.action_manager
But it does not fix the problem.
I have read something related in
Python Testing - Reset all mocks?
where the solution is to use a different library (something that I would like to avoid)
and in Any way to reset a mocked method to its original state? - Python Mock - mock 1.0b1 where it is using different classes to do it.
Is there any possibility to reset the mock in the same class before or after every test?
BTW, this is a unittest question, not a pytest question.
Anyways,
I believe what you're looking for is reset_mock
Here's, in general, how it works:
def test_1(self):
f = MagicMock() # or whatever you're mocking
f()
f.assert_called_once()
f.reset_mock()
f()
f.assert_called_once()
The result will be PASSED
If you want to automate, then you store the mocked thing inside setUp, and in tearDown you call the mocked thing's .reset_mock() method.
def setUp(self, mock1):
self.mock1 = mock1
# ... do other things ...
def tearDown(self):
self.mock1.reset_mock()
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 thought that the following code would result in an error because as far as I have read, a method in a Python class must either have "self" (or any other label, but "self" by convention) as its first argument, or "cls" or similar if the #classmethod decorator is used, or none if the #staticmethod decorator is used.
How come I get no error running this with Python 3.5 in the Terminal, even though test_method does not meet these requirements? It seems to work fine as a static method, but without the decorator.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
class MyClass:
def test_method(args):
print(args[1])
#staticmethod
def static_method():
print("static_method")
#classmethod
def class_method(cls):
print("class_method")
def main(args):
MyClass.test_method(args)
if __name__ == '__main__':
sys.exit(main(sys.argv))
Output:
$ python3 testscript.py "testing"
$ testing
EDIT:
My question could also be phrased differently, drawing attention away from self and to #staticmethod: "How come I'm getting a seemingly working static method without the #staticmethod decorator?"
In Python 2, functions defined in a class body are automatically converted to "unbound methods", and cannot be called directly without a staticmethod decorator. In Python 3, this concept was removed; MyClass.text_method is a simple function that lives inside the MyClass namespace, and can be called directly.
The main reason to still use staticmethod in Python 3 is if you also want to call the method on an instance. If you don't use the decorator, the method will always be passed the instance as the first parameter, causing a TypeError.
There is nothing special about this. In python 3 there is no difference between a function defined inside a class or a function defined outside a class. Both of them are normal functions.
The self that you are talking about here or maybe cls comes into picture only when you access the function through an instance. Hence here you didn't get any error.
However if you modify your code just a little bit to look like the following, then you'd get an error that you expected.
def main(args):
MyClass().test_method(args)
# Should throw an error
EDIT:
#staticmethod will work on both class instances like MyClass().test_method(args)and just a regular direct call like MyClass.test_method(args)
However a regular method(without self in it) can't be called on a class instance. So you will always have to call it as MyClass.test_method(args)
self isn't necessarily required. However, if you want to reference any variable or value that is associated with the object(instantiation of the class) (E.g. for a class about cars, it's speed, self.speed) you'll need to have self as a parameter in the function. For this reason, it's common practice to always have self as an argument, otherwise you aren't really using the class for the right reason.
EDIT:
This will actually throw an error if you do the following:
class a():
def __init__(self, x):
self.asd = x
def hello(x):
print(x)
>>> g = a(4)
>>> g.hello(5)
as when calling "hello", both "self" and "4" will be passed as parameters. It would work in the following instance, which is what I was saying above:
>>> g = a
>>> g.hello(4)
or
>>> a.hello(4)
To add on to the existing answers here and provide a code example:
class MyClass:
def __init__(self):
pass
def myStaticMethod():
print("a static method")
#staticmethod
def myStaticMethodWithArg(my_arg):
print(my_arg)
print("a static method")
MyClass.myStaticMethod()
MyClass.myStaticMethodWithArg("skhsdkj")
abc = MyClass()
abc.myStaticMethodWithArg("avc")
Try removing the #staticmethod decorator and rerunning the code and see what happens! (The very last call will fail since the method is passed in both self and the string input. By adding the decorator, we can guide the interpreter to perform our desired action)
The Mock documentation describes a simple and elegant way of applying patches to all of the tests method inside a TestCase:
#patch('foo.bar')
#patch('foo.baz')
#patch('foo.quux')
#patch('foo.narf')
class FooTest(TestCase):
def test_foo(self, bar, baz, quux, narf):
""" foo """
self.assertTrue(False)
However, one issue I've encountered with this method is that if I'd like to call stop() on one of the patches inside one of the test methods, there doesn't appear to be anyway of getting a reference to the patcher object -- the only thing that is passed into the method is the mock objects, in this case bar, baz, quux, narf.
The only way I've found to solve this problem is to move to the pattern described in the Mock docs where the patchers are instantiated and started inside the setUp method of the TestCase and stopped inside the tearDown method. This fits my purpose, but adds a lot of extra boilerplate and isn't as elegant as the class decorator approach.
Is there another way to solve this problem?
1
Say you want to temporarily restore foo.narf in a method. foo.narf is, in the context of the decorated function, a MagicMock object. This object has a _mock_wraps attribute which will be invoked when the mock is called! So at the top of your module, _narf = foo.narf, and in your test case, foo.narf._mock_wraps = _narf.
The catch is that this will only pass through to the real function, not actually swap it back, which means that some test cases will fail (e.g. if they rely on the function object actually being "itself"). And if your mock has other attributes, that could interfere (I haven't tested much) because the passthrough call to _mock_wraps() comes at the bottom of a method that first considers the other properties of the mock.
2
The patch() decorator involves each patcher (separate copies per method) being added to a list called patchings which is a field of the method itself. I.e. you can access this list as self.test_foo.patchings, and go through to find the one you want.
However, start() and stop() are not actually called when you use patch() as a decorator, and the behavior gets tricky once you start reaching in and changing it. So I wrote this context manager.
class unpatch:
def __init__(self, name, method):
compare = patch(name)
self.patcher = next((
p for p in method.patchings
if p.target == compare.getter()
and p.attribute == compare.attribute
), None)
if self.patcher is None:
raise ValueError(name)
def __enter__(self):
self.patcher.__exit__()
def __exit__(self, *exc_info):
self.patcher.__enter__()
Inside your test case, you use it like this:
with unpatch('foo.narf', self.test_foo):
foo.narf()
Disclaimer: this is hacks.
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()?