I'm trying to mock a chained Django model object in the following dummy method,
# utils.py
def foo_something_exist():
if Foo.objects.get(a='something').exist():
return 'exist'
# test.py
import unittest.mock import patch
import utils
.
.
.
@patch('utils.Foo')
def test_foo_something_exist_returns_none(self, mock_foo):
mock_foo.objects.get.exists.return_value = False
self.assertIsNone(utils.foo_something_exist())
.
.
.
test_foo_something_exist()
fails the test. I discovered that Foo.objects.get(a='something').exist()
in utils.py was a MagicMock object (<MagicMock name='Member.objects.get().exists()' id='xxxxxx'>
) instead of False
, which contributed to the failure of this test function. And yes, I've also tried mock_foo.objects.return_value.get.return_value.exists.return_value = False
, which was mentioned in a post. Pointers/hints for correctly mocking a model object (with its chained methods) is appreciate.
Thank you in advance.
Don't patch the model itself but model.objects and then mock every part of the chain:
@patch('utils.Foo.objects')
def test_foo_something_exist_returns_none(self, mock_foo):
# just to show how to do it with longer chains
# mock_foo.filter.return_value = mock_foo
# mock_foo.exclude.return_value = mock_foo
mock_foo.get.return_value = mock_foo
mock_foo.exists.return_value = False
self.assertIsNone(utils.foo_something_exist())
This also work's with .filter()
, .exclude()
and other model operations. I also find Model Mommy really helpful when testing Django models.