When it's up and running, our application still has one giant dependency: the server. During integration testing, this means that the server-side database needs to be primed with test data, and test suite will result in many requests being sent back and forth. In a large test suite, this can be slow and the database setup can be painful.
A common resolution to this problem is to bypass the server API altogether. When our application makes an Ajax request, we can hijack the XMLHttpRequest
and feed the calling code some static test data instead.
To demonstrate this and show the flexibility of the technique, we'll create a small Jasmine test case that shows how to supply a product store with mock JSON data. Although, faking an Ajax request is really useful in integration tests, this will show off the technique in a succinct way that can be used in both unit and integration testing.
We'll be using a feature of Ext JS that isn't included by default: Simlets
. The classes that implement Simlets
are included in the examples
directory of the Ext JS distribution, so all we have to do is open up the SpecRunner.html
file from earlier in the chapter and amend it to instruct Ext.Loader
to pull in the files from the correct location:
Ext.Loader.setConfig({ enabled: true, paths: { 'Alcohology': '../../app', 'Ext.ux': '../../ext/examples/ux' // added } });
All we've added is the line for the Ext.ux
path. Now, we can build our Jasmine test, so let's dive straight into the code:
describe('Mocking Ajax', function() { var productStore, fakeJsonData = [{ "id":1, "name":"Test Product", "price":"19.99", "description":"Test Product Description" }]; beforeEach(function() { Ext.syncRequire('Ext.ux.ajax.SimManager'), Ext.syncRequire('Alcohology.model.Product'), Ext.ux.ajax.SimManager.init().register({ 'http://localhost:3000/product': { type: 'json', data: fakeJsonData } }); productStore = Ext.create('Ext.data.Store', { model: 'Alcohology.model.Product' }); }); it('Uses fake JSON data', function(done) { productStore.load({ callback: function(records) { expect(records.length).toBe(1); expect(records[0].get('name')).toBe('Test Product'), done(); } }); }); });
Lots going on here! First, we set up a couple of variables, one to contain the productStore
between tests and one containing our fake JSON.
In the beforeEach
function call, we load in the SimletManager
class and the Product
model from Alcohology; Ext.Loader
will pull in the files for us before allowing execution to proceed to the next lines. Next, we set up SimletManager
by registering the URL to be intercepted and the data that should be returned instead of the normal server response.
This is actually all we need to set up a fake request; the rest of the code proceeds as if it were a normal Jasmine test in which we set two expectations after the product store loads, that is, there will be one returned record and its name will be set to Test Product
, just like in the test data.
Running the test through the spec runner sees everything pass as expected and demonstrates the power of this technique. We can disconnect all of our testing from the backend and run independent of a database; test data is supplied directly in the tests and not in a database row somewhere on a server.