简体   繁体   中英

Mocking Django Model and save()

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?

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM