0

My function looks for a Actor object in the database and calls its do_something() method with a passed argument.

from my_app.models import Actor

def my_function(id, stuff):
    actor = Actor.objects.get(id=id)
    return actor.do_something(stuff)

I want my unit test to check two things :
1. my_function finds the Actor I want.
2. my_function calls the actor's do_something method as expected.

from unittest import mock
from django.test import TestCase
from my_app.models import Actor
from my_app.views import my_function


class ViewsTestCase(TestCase):

    @classmethod
    def setUpTestData(cls):
        self.actor = Actor.objects.create(id=42, name='John')

    def test_my_function(self):
        with mock.patch.object(Actor, 'do_something') as mock_do:
            my_function(id=42, stuff='a-short-string')
            mock_do.assert_called_once_with('a-short-string')

This works to make sure my_function called do_something like I wanted but I don't know how to be sure it found the Actor I asked him to find. This test would pass even if my_function found the wrong actor. Is there any way to check that ?

1 Answers1

0

First of all, I am not sure if this is the best practice of asserting on self param of a mocked method.

By adding autospec=True to your mock statement, the self param itself will become accessible in mocked object call_args. To be more clear your test case would be something like this:

from unittest import mock
from django.test import TestCase
from my_app.models import Actor
from my_app.views import my_function


class ViewsTestCase(TestCase):

    @classmethod
    def setUpTestData(cls):
        self.actor = Actor.objects.create(id=42, name='John')

    def test_my_function(self):
        with mock.patch.object(Actor, 'do_something', autospec=True) as mock_do:
                                                      ^^^^^^^^^^^^^
            my_function(id=42, stuff='a-short-string')
            mock_do.assert_called_once_with(self.actor, 'a-short-string')
partizaans
  • 295
  • 2
  • 10
  • That's exactly what I need, Autospeccing made the self param available in the mocked method as you said. Thanks for your help. I also found out someone else asked this and got this answer: https://stackoverflow.com/questions/20257252/how-to-call-self-in-a-mock-method-of-an-object-in-python – mer-sublime Apr 02 '20 at 14:06