Skip to content

Instantly share code, notes, and snippets.

@jonstorer
Created April 24, 2014 20:21
Show Gist options
  • Select an option

  • Save jonstorer/11268262 to your computer and use it in GitHub Desktop.

Select an option

Save jonstorer/11268262 to your computer and use it in GitHub Desktop.
# Given the following tests
Given I create an invitation for "jon@shake.com"
And I create an invitation for "justin@lab49.com"
When I send my invitations
Then I should have sent emails to:
| email |
| jon@shake.com |
| justin@lab49.com |
# If triggering the sending of the emails is synchronous, but sending the emails is asynchronous
# what is the appropriate level of testing for this feature?
@jonstorer

Copy link
Copy Markdown
Author

Basically, triggering the event that would build and send an email is synchronous. But actually building and sending is asynchronous. The current approach is to just add And I wait 1 second before the assertion.

Is there a better approach? What is that better approach?

@yodarjun

Copy link
Copy Markdown

:5
O
And jobs are processed

@jonstorer

Copy link
Copy Markdown
Author

In our system job processing is asynchronous.

@nik

nik commented Apr 24, 2014

Copy link
Copy Markdown

i think you should test it synchronously .. like make a fake queue and do "jobs are processed" like arjun said which just clears the queue

@kylessnell

Copy link
Copy Markdown

whitespace

@benson

benson commented Apr 24, 2014

Copy link
Copy Markdown

don't write tests

@trevormcleod

Copy link
Copy Markdown

@benson +1

@jjgonecrypto

Copy link
Copy Markdown

Why is the message building and sending async in the first place? Surely the building and adding to a queue is synchronous? If you need to assert it hits a third party service, you just mock that.

@jjgonecrypto

Copy link
Copy Markdown

Although if it must be async, then is send timeliness important? I'd say it is. Say you have an NFR to send within 30s, then you can use TimeCop to mock time, jump ahead 30s, and assert that the message was added to the send queue.

@jonstorer

Copy link
Copy Markdown
Author

Nik, I'm not sure we want to add a queue just for testing purposes. We'd be adding a proxy to a system that works.

Benson, #NTD4Life.

Kyle, get that title fixed?

@alexkehayias

Copy link
Copy Markdown

If the email sending returned a promise to you, you could block on the promise.

@alexkehayias

Copy link
Copy Markdown

How about a separate test of sending of emails with an item in a queue. Here you just need to test that it generates a message on the queue.

@jonstorer

Copy link
Copy Markdown
Author

Here's the small example written in node (our use case)

# Observer

User.on 'afterSave', (user) ->
    UserMailer.welcome_email(user).send()

# Model

User.emit 'afterSave', user

@jonstorer

Copy link
Copy Markdown
Author

This entire flow is tested in Unit tests,
User saved, event emitted - done
Event emitted, function called - done
function called, emails sent - done

The question is, from an integration test, where we have a system that diverts processes to a new thread (desired flow).

Should we add a wait? - easy, but prone to race conditions

Break the test up into smaller pieces? - When we get as small as we need to, to be able to know when processes has completed, we will have duplicated the spec test.

Add an eventually step which gives an assert n seconds to be true?

@jjgonecrypto

Copy link
Copy Markdown

Well it's written in coffeescript not node, but you get that.

I agree with @alexkehayias, send() should return a promise in this case. The API should support this after all - what if the SMTP server is down?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment