question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Send-email testing with mail.outbox

See original GitHub issue

I’ve written this simple test:

@when('asking for review and saving')
def act(self):
    site = Site(domain='http://127.0.0.1:8000', name='127.0.0.1')
    site.save()

    request = {'SITE_ID': site.id}
    self.asking_reservation = {'reservation_id': self.reservation1.id}
    self.deserialized_data = AskForReviewSerializer(
        data=self.asking_reservation, context={'request': request})


@then('validate data and send email for review asking')
def test(self):
    with freeze_time(self.reservation_creation_date_plus_two_months):
        assert self.deserialized_data.is_valid() == True
        assert len(mail.outbox) == 0

        self.deserialized_data.save()
        assert len(mail.outbox) == 1

And this is the serializer I’m testing which sends an email when saving:

class AskForReviewSerializer(serializers.Serializer):
    reservation_id = serializers.IntegerField()

    def save(self, *args, **kwargs):
        request = self.context.get('request')

        current_site = get_current_site(request)
        reservation_id = self.validated_data['reservation_id']

        reservation = models.Reservation.objects.get(pk=reservation_id)
        if not reservation.is_reviewable:
            raise serializers.ValidationError('This reservation is not reviewable')

        user = reservation.user

        path = f'/reservations/{reservation_id}/review'
        url = settings.BASE_URL + path
        context = {'current_site': current_site,
                   'user': user,
                   'review_url': url,
                   'request': request}

        get_adapter().send_mail(
            'review/email/ask_for_review',
            user.email,
            context)

    class Meta:
        fields = ('reservation_id', )

But mail.outbox is never affected when running the tests, its length is always zero (I ensured that my EMAIL_BACKEND = ‘django.core.mail.backends.locmem.EmailBackend’)

Full test: https://github.com/coretabs/dorm-portal/blob/master/features/steps/reviews.py#L117

Any idea how can I test the email sending behavior using behave-django?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
bittnercommented, Dec 25, 2018

I searched a bit and I realized that BehaviorDrivenTestCase inherits from the StaticLiveServerTestCase which eventually inherits from TestCase

That is correct. That’s why you should use context.test.client if you want to access the Django TestCase that is launched by behave-django. Then the mail.outbox behavior should match what is described in the Django docs you quote…

Is there any workaround to get the mail.outbox populated during the test? or should I rely on the fact the serializer doesn’t throw any exception and keep it as it is?

I believe, there is a conceptual misunderstanding you’re trapped in. You should understand the way behave works (because behave-django is just marrying behave with Django), and how this affects writing tests for DRF, which you’re obviously using. Maybe you could take a look at similar issues (such as #46) and do some research on how writing tests with DRF in combination with behave. I just found out there is a dedicated project called behave-restful, maybe that makes your job easier? Not sure though.

1reaction
bittnercommented, Dec 23, 2018

I’m not exactly sure what would be the shortest way to helping you, but at first sight I see a few issues with your code:

  1. Your step implementation should have a first argument called context. In your code this is always self. While this is not strictly a technical problem it may obscure the way to find a solution yourself. – Use context as the first argument, the steps are functions not methods (see examples in the project repo).
  2. I’m not sure what you’re doing with Site. Can’t you use Django’s test client, which saves you from hard-coding URL values and such?
  3. You’re importing mail at the top of the module, I think that’s wrong. You should access the mail object that the Django test client has access to. It sounds obvious that otherwise the object is never populated.
  4. Instead of manually creating a client instance and URLs you should be able to move some of the code into the behave setup code and call context.get_url(...).

I like the way you call your step implementation functions (act, test), though! 👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

testing send_email is not working - python - Stack Overflow
Outbox is special type attribute that can't import directly but when you send email using email backend then mail.outbox will work as list ......
Read more >
Testing emails in Django | TimOnWeb
Email messages can and should be tested like any other piece of a web app. ... from django.core import mail print(len(mail.outbox)).
Read more >
Outlook is not sending email - stuck in Outbox
To narrow the cause of the Outbox stuck emails, first of all you should check if you receive an error message while you...
Read more >
Test Mail in Inbox but not in Outbox - WordPress.org
The test mail is send to the receiving mail address, so this is working. But I would like to see the mail in...
Read more >
Configuration passes Test Message, but I still can't send e-mail
I believe my e-mail profile in Outlook is properly configured, ... wind up in the Outbox even though my settings succeed in passing...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found