I would like to mock the following CanonPerson
model
def compute(self, is_send_emails, test_email_address):
cpses = CanonPerson.objects.filter(persons__vpd=6,
persons__country="United States",
persons__role__icontains=';IX;').prefetch_related("persons").using("global")
for cp in cpses:
...
I am quite lost how to mock CanonPerson.objects.filter
to return me an interable collection, so that I can continue.
This is what I have done so far:
def test_X_count(self):
with mock.patch('apps.dbank.models.CanonPerson.objects.filter') as canon_patch:
mock_cp = mock.MagicMock(spec=CanonPerson)
mock_person = mock.MagicMock(spec=Person)
mock_person.vpd = 6
mock_cp.country = "United States"
mock_cp.role = ";IX;"
mock_cp.persons.add(mock_person)
canon_patch.objects.filter.return_value = [mock_cp] // ???
oi = OptinInvites()
oi.compute(False, None)
oi.get_most_recent_email.assert_called_once_with(1)
In the compute function I can see cpses
is a MagicMock type.
However it is not iterable and the for loop
there after, just jumps over it.
I thought by setting the return value to [mock_cp]
I would have created an iterable list?
The line where you assign a return value to canon_patch
is slightly wrong. Where you have:
canon_patch.objects.filter.return_value = [mock_cp]
It should be:
canon_patch.return_value = [mock_cp]
canon_patch
is already the mock of 'objects.filter'.
Your original line would return [mock_cp]
if you called CanonPerson.objects.filter.objects.filter()
.
If you actually want to patch out the CanonPerson
model then your patch line would look something like:
with mock.patch('apps.dbank.models.CanonPerson') as canon_patch:
You might also find that you need to mock it in the location that it is being used, rather than the location you are importing it from. So assuming you are using CanonPerson
in a module called my_module
your patch code in the test might look like this:
with mock.patch('my_module.CanonPerson') as canon_patch: