I'm using Django 1.10 and Celery 4.1
I have a shared_task
which sends an email to the user.
# myapp/tasks.py
@shared_task
def notify_user(user_id):
# TODO: send email and do other stuff here
user = get_object_or_404(User, pk=user_id)
send_mail(
'Subject',
'Body',
'from@example.com',
[user.email],
)
I have another file which contains a function that calls puts that tasks into the queue.
# myapp/utils.py
# ...
def update_queue(self):
# increment no_of_used_referrals by 1
if no_of_used_referrals == 5:
notify_user.apply_async((self.user_id,))
else:
notify_user.apply_async((self.user_id,), eta=new_eta)
Now I am trying to test whether calling update_queue()
(where all required checks passes) sends an email to the user when its executed.
I tried to do the following:
# myapp/tests.py
def update_queue_should_call_notify_user_immediately_after_five_referrals_were_used(self):
with unittest.mock.patch('myapp.tasks.notify_user.apply_async') as notify_user_mock:
# ...
for _ in range(5):
entry.update_queue()
self.assertTrue(notify_user_mock.called)
notify_user_mock.assert_called_with((user_id,))
# TODO: check if email was sent
# I tried using :
# self.assertEqual(len(mail.outbox), 1)
# but it fails with error saying 0 != 1
def test_notify_user_should_send_an_email(self):
notify_user.apply_async((user_id,))
# I tried using:
# self.assertEqual(len(mail.outbox), 1)
# but it fails with error saying 0 != 1
I have set EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'
in my project settings.
Can someone please tell me what is wrong with what I am doing and how to correctly test this case?
EDIT I have updated my code where I excluded mocking - as suggested by @DanielRoseman.
EDIT2 Please see updated files above.
I am simulating referral system. Once 5 referral links associated with a particular user have been used, user get's some nice feature to their profile. Otherwise they have to wait for a specific time, which I set using eta
argument on apply_async
.
Every time I call update_queue
I check if the number of referals is equal to 5(please see updated code above).
- If it is - I want to call
notify_user
immediately, without passingeta
argument value. - If it is not - I increment number of used referral links, revoke old
notify_user
task, create newnotify_user
task with neweta
argument value.
In order to test that I am simulating that behaviour in for-loop, and I want to test whether after 5 iterations(equal to 5 used referral links) an email was sent to the user (for test purposes I use in-memory backend for email).