Typically, I write integration tests in the same manner I write Ember.js apps: totally separated from any HTTP services that the service(s) it might communicate with (e.g. not from within ember-rails
or another server framework integration library).
This creates a somewhat interesting problem when writing integration tests: how to provide mocked data to the application in way that mirror connection to an actual service. I imagine for people who use ember-rails
, they drive integration tests with rspec and fill their database with the correct data before running each test.
For those not integrating with a service, I’d like to see HTTP mocking added to ember-testing to better control what happens when specific responses are returned.
There are three main ways I’ve seen people mock data that comes from the server: fixtures, fake servers, and response emitters.
You’ll be familiar with fixtures if you use a library like ember-data
or ember-model
: you supply an adapter that has some canned data available so when you make a request for, say find('post', 1)
it never goes to the server and just loads your fixture data.
I love fixtures for prototyping but I think they’re not ideal for integration testing for the simple reason that using them will leave your custom adapter code totally unexercised: it’s easy to have a bug with url, HTTP verb, or success handler that goes unnoticed in testing.
Faker servers are probably the most common type of HTTP mocking around. If you’ve used sinon in the browser or something like webmock on the server you’re familiar with this style. You set up the requests you’d like intercepted and the responses they should load ahead of time and then run you tests.
In Ember, it might look something like this:
var server = new FakeServer({
"/rest/ember/show": {
},
"/rest/product": {
products: [
{id: 1, name: "foo"}
]
},
"/rest/ember/create": {
fields: [
{id: 1, name: "summary"}
],
product: {
id: 1,
name: "foo",
components: [
{id: 1, name: "foo component"}
]
}
}
});
I think this approach works well in synchronous environments, where the pattern emerged, but don’t offer the fine-grained control you’d want in asynchronous environments. For example, if you wanted to check of the presence of loading views or test what happens when the response order of two simultaneous requests varies.
Response emitters is the pattern I’ve been using myself. It involves emitting a response at a specific point in the flow of execution by chaining a promise or integrating with the promise-free helpers, should we ever add them
visit("/invoices")
.httpRespond("get", "/api/v1/invoices", {... response object ....})
.click(".remove-invoice")
.httpRespond("delete", "/api/v1/invoices/13917998", {"message":"Invoice was successfully deleted!"})
.then(function(){
equal(find("#flash-message").text(), "Invoice was successfully deleted");
})
Because the {... response object ....}
can get pretty big, we’re also using a factory library, but this is roughly how it works.
So, I need some feedback:
- Should we add HTTP mocking into ember-testing
- Would you prefer a strategy of fixtures, fake servers, response emitting, or something else?
- What extra features would you find handy (e.g. failing a test if there are requests that weren’t responded to or a requests is triggered that isn’t intercepted)?