Chapter 6. Light Speed Unit Testing

In Chapter 4, Asynchronous Testing – AJAX, we saw how including AJAX testing in the application can increase the complexity of the tests. In the example in that chapter, we created a server where the results were predictable. It was basically a complex test fixture. Even though we could have used a real server implementation, it would increase the complexity of the test even more; try changing the state of a server with a database or third-party services from the browser—it is not an easy or scalable solution.

There is also the impact on productivity; these requests take time to process and transmit, which hurts the quick feedback loop that unit testing usually provides.

You can also say that these specs test both the client and the server code and, therefore, could not be considered unit tests; rather, they could be considered integration tests.

A solution to all these problems is to use either stubs or fakes in place of the real dependencies of the code. So, instead of making a request to the server, we use a test double of the server inside the browser.

We are going to use the same example from Chapter 4, Asynchronous Testing – AJAX, and rewrite it using different techniques.

Jasmine stubs

We have already seen some use cases for Jasmine spies. Remember that a spy is a special function that records how it was called. You can think of a stub as a spy with behavior.

We use stubs whenever we want to force a specific path in our specs or replace a real implementation for a simpler one.

Let's revisit the example of the acceptance criteria, "Stock when fetched, should update its share price", by rewriting it using Jasmine stubs.

We know that the stock's fetch function is implemented using the $.getJSON function, as follows:

Stock.prototype.fetch = function(parameters) {
  $.getJSON(url, function (data) {
    that.sharePrice = data.sharePrice;
    success(that);
  });
};

We could use the spyOn function to set up a spy on the getJSON function with the following code:

describe("when fetched", function() {
  beforeEach(function() {
    spyOn($, 'getJSON').and.callFake(function(url, callback) {
      callback({ sharePrice: 20.18 });
    });
    stock.fetch();
  });

  it("should update its share price", function() {
    expect(stock.sharePrice).toEqual(20.18);
  });
});

But this time, we will use the and.callFake function to set a behavior to our spy (by default, a spy does nothing and returns undefined). We make the spy invoke its callback parameter with an object response ({ sharePrice: 20.18 }).

Later, at the expectation, we use the toEqual assertion to verify that the stock's sharePrice has changed.

To run this spec, you no longer need a server to make the requests to, which is a good thing, but there is one issue with this approach. If the fetch function gets refactored to use $.ajax instead of $.getJSON, then the test will fail. A better solution, provided by a Jasmine plugin called jasmine-ajax, is to stub the browser's AJAX infrastructure instead, so the implementation of the AJAX request is free to be done in different manners.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset