I need to create some kind of MockMixin
for my tests. It should include mocks for everything that calls external sources.
For example, each time I save model in admin panel I call some remote URLs. It would be good, to have that mocked and use like that:
class ExampleTestCase(MockedTestCase):
# tests
So each time I save model in admin, for example in functional tests, this mock is applied instead of calling remote URLs.
Is that actually possible? I'm able to do that for 1 particular test, that is not a problem. But it'd be more useful to have some global mock because I use it a lot.
According to the mock
documentation:
Patch can be used as a TestCase class decorator. It works by
decorating each test method in the class. This reduces the boilerplate
code when your test methods share a common patchings set.
This basically means that you can create a base test class with @patch
decorator applied on it that would mock your external calls while every test method inside would be executed.
Also, you can use start()
and stop()
patcher's methods in setUp()
and tearDown()
methods respectively:
class BaseTestCase(TestCase):
def setUp(self):
self.patcher = patch('mymodule.foo')
self.mock_foo = self.patcher.start()
def tearDown(self):
self.patcher.stop()
Just to add to alecxe's answer, if you are using teardown()
then according to the docs
you must ensure that the patching is “undone” by calling stop
. This can be fiddlier than you might think, because if an exception is raised in the setUp
then tearDown
is not called.
If an exception is raised in your tests, your patching won't be undone. A better way would be to call addCleanup()
inside your setUp()
. Then you can omit the tearDown()
method altogether.
class BaseTestCase(TestCase):
def setUp(self):
self.patcher = patch('mymodule.foo')
self.mock_foo = self.patcher.start()
self.addCleanup(self.patcher.stop) # add this line