title: How to test if email was sent after executing celery task
body: <p>I'm using Django 1.10 and Celery 4.1</p>
  
  <p>I have a <code>shared_task</code> which sends an email to the user.</p>
  
  <pre><code># 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],
      )
  </code></pre>
  
  <p>I have another file which contains a function that calls puts that tasks into the queue. </p>
  
  <pre><code># 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)
  </code></pre>
  
  <p>Now I am trying to test whether calling <code>update_queue()</code> (where all required checks passes) sends an email to the user when its executed.</p>
  
  <p>I tried to do the following:</p>
  
  <pre><code># 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
  </code></pre>
  
  <p>I have set <code>EMAIL_BACKEND = 'django.core.mail.backends.locmem.EmailBackend'</code> in my project settings.</p>
  
  <p>Can someone please tell me what is wrong with what I am doing and how to correctly test this case?</p>
  
  <p><strong>EDIT</strong>
  I have updated my code where I excluded mocking - as suggested by @DanielRoseman.</p>
  
  <p><strong>EDIT2</strong>
  Please see updated files above.</p>
  
  <p>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 <code>eta</code> argument on <code>apply_async</code>.</p>
  
  <p>Every time I call <code>update_queue</code> I check if the number of referals is equal to 5(please see updated code above).</p>
  
  <ul>
  <li>If it is - I want to call <code>notify_user</code> immediately, without passing <code>eta</code> argument value. </li>
  <li>If it is not - I increment number of used referral links, revoke old <code>notify_user</code> task, create new <code>notify_user</code> task with new <code>eta</code> argument value.</li>
  </ul>
  
  <p>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).</p>