Mocking callable objects using Mockito for Python - python

I have a function of the form:
def my_function(arg):
f = get_anonymous_function(arg)
return f()
I want to test this function in mockito with py.test.
So I write my test as follows:
def test_my_function(when):
arg = mock()
f = mock()
when(my_module).get_anonymous_function(arg).thenReturn(f)
expected = mock()
when(f).thenReturn(expected)
actual = my_module.my_function(arg)
assert expected == actual
When I run such a test, actual is None. If I change when to when2, Mockito complains TypeError: can't guess origin of 'f'.
My provisional solution is to use f = lambda: return expected, and then skip the second when. This works, but feels not quite right. Is there a better way?
PS: "Don't use Mockito" is not really the answer I'm looking for. Likewise, "write my_function better" is not an option, as this sort of situation arises routinely when using external packages.

Figured it out. From the documentation (with typo corrected):
Mocks are by default callable. Configure the callable behavior using
when:
dummy = mock()
when(dummy).__call__(1).thenReturn(2)

Related

Why do we pass in a first/second anonymous argument in a mock test?

I am quite new to decorators, and I am using it in mocking a function; can someone kindly explain the following:
class TestTSE(...):
...
#patch.object(TSESubparser, 'parse_er_data', return_value=None)
def test_receive_timestamp(self, mock_parse_er_data_to_nothing):
packet = MagicMock(capture_timestamp=123456)
self.on_packet(packet)
assert self.context.capture_tstamp == 123456
I don't quite understand why we are passing a second argument mock_parse_er_data_to_nothing. I tried running the test without it and it fails.
I understand that we can call this function anything that we want? - why is this. And it is advisable that it starts with mock

Unittest check if main called methods

I have a main method that looks like this:
class Example:
...
def main(self):
self.one()
self.two(list)
self.three(self.four(4))
How to check if the calling main it calls the following methods inside it?
I have tried:
def setUp(self):
self.ex = example.Example()
def test_two(self):
# testing method two that has only list.append(int) and returns list
mock_obj = Mock()
self.ex.two(mock_obj, 1)
self.assertEqual(call.append(1),mock_obj.method_calls[0]) # works fine
mock_obj.method.called # throws False ...why?
def test_main(self):
with patch('example.Example') as a:
a.main()
print(a.mock_calls) # [call.main()]
...
def test_main(self):
mock_obj = Mock()
self.ex.main(mock_obj) # throws TypeError: main() takes exactly 1 argument (2 given)
print(mock_obj.method_calls) # expected one, two, three and four method calls
Realy need any help to be honest..
Using Python 2.6.6 with unittest and mock modules
With unit-testing you could in principle test if these four functions would actually be called. And, you could certainly do this by mocking all of them. However, you would need integration tests later anyway to be sure that the functions were called in the proper order, with the arguments in the proper order, arguments having values in the form expected by the callee, return values being in the expected form etc.
You can check all these things in unit-testing - but this has not much value, because if you have wrong assumptions about one of these points, your wrong assumptions will go into both your code and your unit-tests. That is, the unit-tests will test exactly against your wrong assumptions and will pass. Finding out about your wrong assumptions requires an integration test where the real caller and callee are brought together.
Summarized: Your main method is interaction dominated and thus should rather be tested directly by interaction-testing (aka integration-testing) rather than by unit-testing plus subsequent interaction-testing.

Mocking file reads using patch decorator and side_effect

I am testing a function that reads a file, does operations to the contents and returns a value depending on what it sees. The function testme I test lives in module.py. I am running python 2.7. I know I can accomplish this with
import unittest
import module
from mock import patch, mock_open
TestTestMe(unittest.TestCase):
...
def test_test_me(self):
with patch('module.open', mock_open(read_data='1 2')) as _:
self.assertRaises(IndexError, module.testme, 'foo')
with patch('module.open', mock_open(read_data='1 2 3')) as _:
self.assertEquals(module.testme('foo'), 3)
etc.
However, I would like to (mostly to prevent repeated use of with statement, and also to be able to dynamically generate various read_data) be able to do this using the #patch as decorator defining my read_data with a function. Something like this. I will not repeat the class definition and imports.
def give_contents(x):
if x == 'correct':
return mock_open(read_data='1 2 3')
else:
return mock_open(read_data='a b c')
and then using the test function like:
#patch(module.open, side_effect=give_contents)
def test_test_me(self):
self.assertEquals(module.testme('correct'), 3)
I keep running into TypeErrors such as
TypeError: test_testme() takes exactly 1 argument (2 given)
however I try to get around this. This is driving me crazy. Guidance would be greatly appreciated. If you want some additional details I may have omitted, please ask for specifics, and I will provide those.
Edit: Implementation of the function to be tested as requested. I'm sorry I omitted this as 'unimportant', it obviously should have been there.
def testme(filepath):
with open(filepath, 'r') as f:
line = f.readline().strip().split()
return int(line[2])
I would consider the following:
from io import TextIOWrapper, BytesIO
from unittest.mock import patch, mock_open
def open_file(filename):
with open(filename, 'r') as f:
data = f.readline()
return data
def string_byte_me(input):
return TextIOWrapper(BytesIO(input))
def side_effect(filename, mode):
if filename == 'correct':
return string_byte_me(b'1 2 3')
else:
return string_byte_me(b'a b c')
m = mock_open()
m.side_effect = side_effect
#patch('builtins.open', m)
def test_open_file():
assert open_file('correct') == '1 2 3'
assert open_file('incorrect') == 'a b c'
test_open_file() # Passes.
This works by adding side_effect to the mock_open object after instantiation (not sure if there is a better way?). The returned side_effect must be capable of .readline() hence the TextIOWrapper.
As I stated in a previous comment :
I'm not sure about that since you didn't include any occurence of a test_testme function in the code you gave us. However if it is the module.testme method you are using, you forgot to declare the string parameter in the method definition. Depending on your feedback, I might make this an answer.
Edit : I wasn't exactly on the spot, as the argument your forgot was rather the self.
Apparently, this worked for you, so here is the promised answer.
Assuming the module.testme method you talked about is a function looking like :
TestTestMe(unittest.TestCase):
...
def testme(filepath):
with open(filepath, 'r') as f:
line = f.readline().strip().split()
return int(line[2])
This function, however, is rather a method, as you are accessing it from an object. (doing module.testme('foo')), and as such, the first argument given to the call will always be the implicit self.
So what happens is, you have your function expecting one argument, a string ('foo'), but two are given even if self isn't explicit : '(self, 'foo')'.
Thus the error, which says you receive more arguments than you ask for.
The correction is quite simple : add self to the expected arguments of testme.
Which would then become:
def testme(self, filepath):
with open(filepath, 'r') as f:
line = f.readline().strip().split()
return int(line[2])
Hope this helped. Errors concerning amount of arguments are really often due to this kind of forgotten details. Although you don't need the self, it will always be passed as first positional argument (in python).
Have a nice day !
PS: Sorry for some strange english phrasing and repetitions.

How to write unittest for variable assignment in python?

This is in Python 2.7. I have a class called class A, and there are some attributes that I want to throw an exception when being set by the user:
myA = A()
myA.myattribute = 9 # this should throw an error
I want to write a unittest that ensures that this throws an error.
After creating a test class and inheriting unittest.TestCase, I tried to write a test like this:
myA = A()
self.assertRaises(AttributeError, eval('myA.myattribute = 9'))
But, this throws a syntax error. However, if I try eval('myA.myattribute = 9'), it throws the attribute error, as it should.
How do I write a unittest to test this correctly?
Thanks.
You can also use assertRaises as a context manager:
with self.assertRaises(AttributeError):
myA.myattribute = 9
The documentation shows more examples for this if you are interested. The documentation for assertRaises has a lot more detail on this subject as well.
From that documentation:
If only the exception and possibly the msg arguments are given, return a context manager so that the code under test can be written
inline rather than as a function:
with self.assertRaises(SomeException):
do_something()
which is exactly what you are trying to do.
self.assertRaises takes a callable (and optionally one or more arguments for that callable) as its argument; you are providing the value that results from calling the callable with its arguments. The correct test would be self.assertRaises(AttributeError, eval, 'myA.myattribute = 9')
# Thanks to #mgilson for something that actually works while
# resembling the original attempt.
self.assertRaises(AttributeError, eval, 'myA.myattribute = 9', locals())
However, you should use assertRaises as a context manager, which allows you to write the much more natural
with self.assertRaises(AttributeError):
myA.myattribute = 9

Unittest __unittest_skip__ access in beforeTest method

I am using the skip decorator for a test:
#skip('I want this to skip')
def test_abc(self):
I also have a nose plugin to report test results with a defined
def beforeTest(self, *args, **kwargs):
the test case test_abc is getting captured by the beforeTest method. How can I check for the decorator value in my beforeTest method?
I see that the definition of unittest decorator has the following code:
test_item.__unittest_skip__ = True
test_item.__unittest_skip_why__ = reason
But I dont know how to access it from beforeTest.
When running args[0].test has the test case object but I can seem to find where __unittest_skip__ is defined
Thanks!
Looking at the source code, there doesn't seem to be a clean way to do this. TestCase seems to know what method it is testing based on the _testMethodName implementation detail. If you have a reference to the running test case (maybe args[0].test? I'm not familiar with nose...) you could use that, or you could parse it out of the return value from TestCase.id(). Assuming you aren't doing something really funky, it would be something like:
test_name = test_case.id().rsplit('.', 1)[-1]
test_method = getattr(test_case, test_name)
if getattr(test_method, '__unittest_skip__', False):
# Method skipped. Don't do normal stuff.

Categories

Resources