I have the following scenario:
in my models.py
class FooBar(models.Model):
description = models.CharField(max_length=20)
in my utils.py file.
from models import FooBar
def save_foobar(value):
'''acts like a helper method that does a bunch of stuff, but creates a
FooBar object and saves it'''
f = FooBar(description=value)
f.save()
in tests.py
from utils import save_foobar
@patch('utils.FooBar')
def test_save_foobar(self, mock_foobar_class):
save_mock = Mock(return_value=None)
mock_foobar_class.save = save_mock
save_foobar('some value')
#make sure class was created
self.assertEqual(mock_foobar_class.call_count, 1) #this passes!!!
#now make sure save was called once
self.assertEqual(save_mock.call_count, 1) #this fails with 0 != 1 !!!
This is a simplified version of what I'm trying to do... so please don't get hungup on why I have a utils file and a helper function for this (in real life it does several things). Also, please note, while simplified, this is an actual working example of my problem. The first call to test call_count returns 1 and passes. However, the second one returns 0. So, it would seem like my patch is working and getting called.
How can I test that not only an instance of FooBar gets created, but also that the save method on it gets called?
The save method is an inherited method from models. Model which is executed to save an instance into a particular Model. Whenever one tries to create an instance of a model either from admin interface or django shell, save() function is run.
To save data in Django, you normally use . save() on a model instance. However the ORM also provides a . update() method on queryset objects.
When mocking in a test, we are in a certain way making fun of our software or of the function we are testing, simulating the behaviour of a specific external functionality. In Python there is a package in the standard library that helps us apply mocks during our tests.
Here is your problem, you currently have:
mock_foobar_class.save = save_mock
since mock_foobar_class
is a mocked class object, and the save
method is called on an instance of that class (not the class itself), you need to assert that save is called on the return value of the class (aka the instance).
Try this:
mock_foobar_class.return_value.save = save_mock
I hope that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With