Avoid passing second param to every unit test using mock.patch - python

I'm mocking my RpcClient class for all of my unit tests like this:
import unittest2
from mock import patch
#patch('listeners.RpcClient')
class SomeTestCase(unittest2.TestCase):
test_something(self, mock_api):
...
test_something_else(self, mock_api):
...
For most of my tests I don't want to do any assertions using the mock object, all I want to do is patch the class so the RpcClient doesn't attempt to connect and fire requests for each of my tests (I have it hooked up to a post save event on one of my models).
Can I avoid passing in mock_api into every single one of my tests?

I ended up doing the mocking in setUp using patcher.start():
def setUp(self):
self.rpc_patcher = patch('listeners.RpcClient')
self.MockClass = rpc_patcher.start()
def tearDown(self):
self.rpc_patcher.stop()
So I don't have to decorate any of my test cases and don't have to add any extra arguments to my tests.
More info:
http://docs.python.org/dev/library/unittest.mock#patch-methods-start-and-stop

Can you just set a default parameter to mock_api?
def test_something(self, mock_api=None):
...
def test_something_else(self, mock_api=None):

You could make use mock.patch as a context manager for when you call the SUT. Something like:
import unittest2
from mock import patch
class SomeTestCase(unittest2.TestCase):
def call_sut(self, *args, **kwargs):
with mock.patch('listeners.RpcClient'):
# call SUT
def test_something(self):
self.call_sut()
# make assertions
def test_something_else(self):
self.call_sut()
# make assertions

Related

Check if pytest fixture is called once during testing

Does pytest provides functionality like unittest.mock to check if the mock was actually called once(or once with some parameter)?
Sample Source code:
my_package/my_module.py
from com.abc.validation import Validation
class MyModule:
def __init__(self):
pass
def will_call_other_package(self):
val = Validation()
val.do()
def run(self):
self.will_call_other_package()
Sample test code for the above source code:
test_my_module.py
import pytest
from pytest_mock import mocker
from my_package.my_module import MyModule
#pytest.fixture
def mock_will_call_other_package(mocker):
mocker.patch('my_package.my_module.will_call_other_package')
#pytest.mark.usefixtures("mock_will_call_other_package")
class TestMyModule:
def test_run(self):
MyModule().run()
#check `will_call_other_package` method is called.
#Looking for something similar to what unittest.mock provide
#mock_will_call_other_package.called_once
If you want to use a fixture that does the patching, you can move the patching into a fixture:
import pytest
from unittest import mock
from my_package.my_module import MyModule
#pytest.fixture
def mock_will_call_other_package():
with mock.patch('my_package.my_module.will_call_other_package') as mocked:
yield mocked
# the mocking will be reverted here, e.g. after the test
class TestMyModule:
def test_run(self, mock_will_call_other_package):
MyModule().run()
mock_will_call_other_package.assert_called_once()
Note that you have to use the fixture parameter in the test. Just using #pytest.mark.usefixtures will not give you access to the mock itself. You can still use it to be effective in all tests in the class, if you don't need to access the mock in all tests (or use autouse=True in the fixture).
Also note that you don't need pytest-mock here - but as mentioned by #hoefling, using it makes the fixture better readable, because you don't need the with clause :
#pytest.fixture
def mock_will_call_other_package(mocker):
yield mocker.patch('my_package.my_module.will_call_other_package')
As an aside: you don't need to import mocker. Fixtures are looked up by name, and available automatically if the respective plugin is installed.
You could try this:
import pytest
from my_package.my_module import MyModule
def test_run(mocker):
mocker.patch('my_package.my_module.will_call_other_package')
MyModule().run()
mock_will_call_other_package.assert_called_once()
First of all, you may not need the burden of an external library such as pytest_mock, because pytest already got you covered using the integration with unittest.
You also do not need to use the usefixtures because whenever you need a fixture, you just receive it in your test method.
An ideal scenario based on your own code would look similar to this:
import pytest
from unittest.mock import patch
from com.abc.validation import Validation
class MyModule:
def __init__(self):
pass
def will_call_other_package(self):
val = Validation()
val.do()
def run(self):
self.will_call_other_package()
#pytest.fixture
def call_other_module():
with patch("my_package.my_module.MyModule.will_call_other_package") as _patched:
yield _patched
class TestMyModule:
def test_run_will_call_other_package(self, call_other_module):
call_other_module.assert_not_called()
obj = MyModule()
call_other_module.assert_not_called()
obj.run()
call_other_module.assert_called_once()
And also if you want to make sure that you did infact patch the target MyModule.will_call_other_package, modify your test like this:
class TestMyModule:
def test_run_will_call_other_package(self, call_other_module):
call_other_module.assert_not_called()
obj = MyModule()
call_other_module.assert_not_called()
obj.run()
call_other_module.assert_called_once()
assert False, (MyModule.will_call_other_package, call_other_module)
And you'll see something similar to this:
AssertionError: (<MagicMock name='will_call_other_package' id='140695551841328'>, <MagicMock name='will_call_other_package' id='140695551841328'>)
As you can see the id of both objects are the same, confirming our experiment was successful.

Passing arguments to fixture in TestCase with pytest

How to pass custom arguments to fixture inside test method of unittest.TestCase derived class using pytest?
After searching for definitely too long time I managed to invent solution with usage of doc and threads about wrapping fixtures. I hope somebody will find it useful.
conftest.py
import pytest
#pytest.fixture()
def add(request):
def wrapped(a=10, b=5):
return a + b
request.cls.add = wrapped
add_test.py
import pytest
from unittest import TestCase
#pytest.mark.usefixtures('add')
class AddTestCase(TestCase):
def test_add(self):
# parameters can be passed inside test method
result = self.add(2, 2)
assert result == 4

How to use the patch decorator to patch a method instead of using it with context manager

I have the following Python unit test case.
import json
import rules
from rules import RULES
import models
from django.test import TestCase
from mock import patch
class RulesTest(TestCase):
request_length = 484
url = "http://www.ndtv.com"
def setUp(self):
har_data = open('/Users/rokumar/SiteAnalysisGit/Src/hct/exportfiles/test.har')
self.data = json.load(har_data)
self.rule = models.Rule(name=RULES.DNS,user=None,
threshold=None)
self.rule.save()
def tearDown(self):
self.rule.delete()
def test_parse_har(self):
with patch.object(rules, 'add_dns_analysis', return_value=None) as \
dns_mock:
dns_mock.add_dns_analysis('test result', 'test url')
result = rules.parse_har(self.data,[self.rule],RulesTest.url)
self.assertEqual(result[RULES.TOTAL_REQUESTS], 484)
Can I mock the add_dns_analysis method using #patch decorator instead of context manager and when should I use either of them.
In your case you can use either decorator and context and even patch instead of patch.object. For instance your test could be rewrite as
#patch.object(rules, 'add_dns_analysis', return_value=None)
def test_parse_har(self,dns_mock):
dns_mock.add_dns_analysis('test result', 'test url')
result = rules.parse_har(self.data,[self.rule],RulesTest.url)
self.assertEqual(result[RULES.TOTAL_REQUESTS], 484)
or
#patch('rules.add_dns_analysis', return_value=None)
def test_parse_har(self,dns_mock):
dns_mock.add_dns_analysis('test result', 'test url')
result = rules.parse_har(self.data,[self.rule],RulesTest.url)
self.assertEqual(result[RULES.TOTAL_REQUESTS], 484)
EDIT
I wrote that answer by thing the question was When to use... instead of How to use.... So the next part is about When to use the patch decorator to patch a method instead of using it with context manager.
But in general by decorator you can obtain cleaner code than the context version. For instance if need to patch more object the decorator version looks like
#patch('amodule.A.a_method')
#patch('amodule.A.b_method')
#patch('amodule.B.c_method')
def test_mytest(self,bc_mock,ab_mock,aa_mock):
...
but the context version looks like:
#patch('amodule.A.a_method')
#patch('amodule.A.b_method')
#patch('amodule.B.c_method')
def test_mytest(self):
with patch('amodule.A.a_method') as aa_mock:
with patch('amodule.A.b_method') as ab_mock:
with patch('amodule.B.c_method') as bc_mock:
....
I think that in that case decorator's version is real better.
patch decorator is powerful but not a silver bullet. For instance if in your test you need configure something in your patch that depend from other object or your class you can't use decorator:
def mytest(self):
foo = Foo()
with patch('amodule.A.a_method', return_value=self.a_return, my_property=foo) as m:
...
The last example where you have to use with instead of patch is when you need more one patch of the same object in the same test or you need both patched and unpatched version:
def mytest(self):
with patch('amodule.A.a_method', return_value="first") as m:
....
with patch('amodule.A.a_method', return_value="second") as m:
....
amodule.A.a_method() #original
Finally you can obtain a complete fine grain by a direct use of enter() exit() methods of the patch object but I think that is a little bit out of scope in that answer.
Yes, you could use #patch decorator. In my opinion, there is no big difference between both decisions.

Patching a module imported and instantiated in the SUT

I'm trying to run unit tests on a class that imports two other modules, and I'm trying to patch out those modules using mock. One of these modules is instantiated in the class I'm testing, and I have not been able to patch it out. It appears that I have managed to patch out the other one.
What is the best way to patch out the sequence.processor module in this code?
Directory structure
logger.py
parser/
__init__.py
docparser.py
sequence/
__init__.py
processor.py
tests/
testdocparser.py
/parser/docparser.py
import logger
from sequence.processor import Processor
class DocParser(object):
def __init__(self, reader_writer):
self.processor = Processor(reader_writer)
def write_and_parse(self, products):
logger.log(products)
self.processor.process(products)
/tests/testdocparser.py
import unittest
from mock import MagicMock, patch
from parser import docparser
class DocParserTests(unittest.TestCase):
def setUp(self):
self.mock_writer = MagicMock()
self.docparser = docparser.DocParser(self.mock_writer)
#patch("parser.docparser.logger") # This seems to be patched properly
#patch("parser.docparser.Processor") # This is not patched
def test_write_and_parse(self, mock_logger, mock_proc):
products = "products"
self.docparser.write_and_parse(products)
You patch Processor in test_write_and_parse() but it's instantiated in DocParser.__init__() which is called from setUp().
This should work, though I haven't tested it:
class DocParserTests(unittest.TestCase):
def setUp(self):
self.mock_writer = MagicMock()
with patch('parser.docparser.Processor'):
self.docparser = docparser.DocParser(self.mock_writer)
#patch("parser.docparser.logger")
def test_write_and_parse(self, mock_logger):
products = "products"
self.docparser.write_and_parse(products)
I've used context manager instead of decorator to avoid changing setUp() signature (adding an argument).
Also the order of mock arguments for test_write_and_parse() is incorrect in your code. Here's an excerpt from mock docs:
When you nest patch decorators the mocks are passed in to the decorated function in the same order they applied (the normal python order that decorators are applied). This means from the bottom up...
Correct order:
#patch("parser.docparser.logger") # This seems to be patched properly
#patch("parser.docparser.Processor") # This is not patched
def test_write_and_parse(self, mock_proc, mock_logger):
# ...
Of cource, it doesn't really matter in your particular case because mock_proc and mock_logger are not used later.

How can I define one setup function for all nosetests tests?

I'm using google app engine with python and want to run some tests using nosetest.
I want each test to run the same setup function. I have already a lot of tests, so I don't want to go through them all and copy&paste the same function. can I define somewhere one setup function and each test would run it first?
thanks.
You can write your setup function and apply it using the with_setup decorator:
from nose.tools import with_setup
def my_setup():
...
#with_setup(my_setup)
def test_one():
...
#with_setup(my_setup)
def test_two():
...
If you want to use the same setup for several test-cases you can use a similar method.
First you create the setup function, then you apply it to all the TestCases with a decorator:
def my_setup(self):
#do the setup for the test-case
def apply_setup(setup_func):
def wrap(cls):
cls.setup = setup_func
return cls
return wrap
#apply_setup(my_setup)
class MyTestCaseOne(unittest.TestCase):
def test_one(self):
...
def test_two(self):
...
#apply_setup(my_setup)
class MyTestCaseTwo(unittest.TestCase):
def test_one(self):
...
Or another way could be to simply assign your setup:
class MyTestCaseOne(unittest.TestCase):
setup = my_setup

Categories