Jasmine Ajax is an official plugin developed to help out the testing of AJAX requests. It changes the browser's AJAX request infrastructure to a fake implementation.
This fake (or mocked) implementation, although simpler, still behaves like the real implementation to any code using its API.
Before we dig into the spec implementation, first we need to add the plugin to the project. Go to https://github.com/jasmine/jasmine-ajax/ and download the current release (which should be compatible with the Jasmine 2.x release). Place it inside the lib
folder.
It is also needed to be added to the SpecRunner.html
file, so go ahead and add another script:
<script type="text/javascript" src="lib/mock-ajax.js"></script>
Whenever you are using jQuery to make AJAX requests, under the hood it is actually using the XMLHttpRequest
object to perform the request.
XMLHttpRequest
is the standard JavaScript HTTP API. Even though its name suggests that it uses XML, it supports other types of content such as JSON; the name has remained the same for compatibility reasons.
So, instead of stubbing jQuery, we could change the XMLHttpRequest
object with a fake implementation. That is exactly what this plugin does.
Let's rewrite the previous spec to use this fake implementation:
describe("when fetched", function() { beforeEach(function() { jasmine.Ajax.install(); }); beforeEach(function() { stock.fetch(); jasmine.Ajax.requests.mostRecent().respondWith({ 'status': 200, 'contentType': 'application/json', 'responseText': '{ "sharePrice": 20.18 }' }); }); afterEach(function() { jasmine.Ajax.uninstall(); }); it("should update its share price", function() { expect(stock.sharePrice).toEqual(20.18); }); });
Drilling the implementation down:
XMLHttpRequest
object by a fake implementation using the jasmine.Ajax.install
function.stock.fetch
function, which will invoke $.getJSON
, creating XMLHttpRequest
anew under the hood.jasmine.Ajax.requests.mostRecent().respondWith
function to get the most recently made request and respond to it with a fake response.We use the respondWith
function, which accepts an object with three properties:
status
property to define the HTTP status code.contentType
(JSON in the example) property.responseText
property, which is a text string containing the response body for the request.Then, it's all a matter of running the expectations:
it("should update its share price", function() { expect(stock.sharePrice).toEqual(20.18); });
Since the plugin changes the global XMLHttpRequest
object, you must remember to tell Jasmine to restore it to its original implementation after the test runs; otherwise, you could interfere with the code from other specs (such as the Jasmine jQuery fixtures module). Here's how you can accomplish this:
afterEach(function() { jasmine.Ajax.uninstall(); });
There is also a slightly different approach to write this spec; here, the request is first stubbed (with the response details) and the code to be exercised is executed later.
The previous example is changed to the following:
beforeEach(function() { jasmine.Ajax.stubRequest('http://localhost:8000/stocks/AOUE').andReturn({ 'status': 200, 'contentType': 'application/json', 'responseText': '{ "sharePrice": 20.18 }' }); stock.fetch(); });
It is possible to use the jasmine.Ajax.stubRequest
function to stub any request to a specific request. In the example, it is defined by the URL http://localhost:8000/stocks/AOUE
, and the response definition is as follows:
{ 'status': 200, 'contentType': 'application/json', 'responseText': '{ "sharePrice": 20.18 }' }
The response definition follows the same properties as the previously used respondWith
function.