Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I mock a method globally for all tests in python

My Django project has hundreds of test in various modules across a number of apps. Recently we added a feature where an email gets sent (via sendgrid) on creation of a User object (using Django Signals).

The problem we ran into is that when running tests, many users are created either explicitly or as fixtures. This results in many hundreds of emails being sent on each test cycle, and because most of them are invalid we get hundreds of bounces. In addition to the costs involved, Sendgrid actually suspended our account briefly due to the odd behaviour.

Obviously I can mock the call on each test individually, however this would have to take place in hundreds of places, and we would have to remember to do it on all future tests we create.

Is there an easier way to globally mock a particular chunk of code for all tests (leaving it intact for when actually running of course)

like image 296
James Hardy Avatar asked Feb 23 '16 19:02

James Hardy


1 Answers

Two ways that I have used in a big django project

Assuming a: my_mock = patch("myapp.mymodule.MyClass.my_method")

1) You can add a mock inside a custom test runner class:

from mock import patch
from django.test.runner import DiscoverRunner

class MyTestRunner(DiscoverRunner):
    @my_mock
    def run_tests(self, test_labels, **kwargs):
         return super(MyTestRunner, self).run_tests(test_labels, **kwargs)

2) You can add a mock on a custom base test class:

from mock import patch
from django.test import TestCase

class MyTestCase(TestCase):

   def setUp(self):
      super(MyTestCase, self).setUp()
      my_mock.start()

   def tearDown(self):
      super(MyTestCase, self).tearDown()
      my_mock.stop()
like image 183
djangonaut Avatar answered Sep 28 '22 13:09

djangonaut