Search code examples
djangodjango-testingmagicmock

MagicMock not called inside django signals


I have some model

class Foo(models.Model):
    name = models.CharField(...)
    url = models.URLField(...)

foo_pre_save_(sender, instance, *args, **kwargs):
    r = urlopen(instance.url)     # Magic mock is not called
    html = bs4.BeautifulSoup(r.read(), "html5lib")
    instance.name = html.find(name="title").text

with a test

def test_get_site_name(self):
    with mock.patch('urllib.request.urlopen') as get_mock:
        get_mock.return_value = mock_response = mock.MagicMock()
        mock_response.read.return_value = "<title>facebook</title>

        foo = Foo.objects.create(
                url = 'www.facebook.com'
            )

    self.assertEqual(foo.name, "facebook")

But the pre_save signal is actually going out and hitting the supplied url, and not getting the mock response

I believe this has to do with the scope of patch; however, I'm not sure how to fix it.


Solution

  • Your problem is likely this line:

    with mock.patch('urllib.request.urlopen') as get_mock:
    

    You're patching a name where the function is defined, instead of where it is imported. Try this:

    # `myapp.models` is the module containing `Foo`
    with mock.patch('myapp.models.urlopen') as get_mock:
    

    For more information, see the section where to patch in the docs.