Blog

REST 2016 - Testing your API with Jasmine

Gavin Pickin March 25, 2016

Spread the word

Gavin Pickin

March 25, 2016

Spread the word


Share your thoughts

Are you writing APIs? Going to start writing APIs? Now is the time to start testing. Sounds familiar, it should, because you’ll be hearing that a LOT. Do it early, and often, and reap the benefits as the project grows. Whether you are using CFML or not, TestBox is a great way to test your APIs, like I showed you in a previous blog post ( Testing your API with TestBox ). Today, we’ll look at Jasmine, and see how you can test your APIs with Javascript… and a couple of “gotchas” I ran into as well.

One great thing about TextBox and Jasmine, is they use almost identical syntax, so a lot of your tests are essentially interchangeable. Thank you smart people at Ortus for studying other languages and standards, it helps.

I’ll assume you have got Jasmine installed and setup. There is a lot of good information on that, but if you are attending dev.Objective() in Bloomington MN this year, I am presenting on “How to write Testable Javascript” where I go into other Javascript Testing tools, and installing Jasmine.

In this tests, we’re firing the login button event handler, which hits an API with some data, and returns a result to the processLoginAjaxDone() function. If the API fails, it calls processLoginAjaxFail().

The first attempt at writing this test looks like this

describe("Login API", function() {
   it("should return a failing Ajax Response", function() {
       spyOn( window, "processLoginAjaxDone");
       spyOn( window, "processLoginAjaxFail");
       loginButtonEventHandlerProcess( 'gavin@gavin.co.nz', 'password');
       expect(processLoginAjaxDone).toHaveBeenCalled();
       expect(processLoginAjaxDone).toHaveBeenCalledWith( ‘{"RESULT":400}' );
       expect(processLoginAjaxFail).not.toHaveBeenCalled();
   });
});

 

Looking at this, we’re spying on the functions we’re expecting to be called.
Lets run this… and we’ll get an unexpected result… why?

loginButtonEventHandlerProcess( 'gavin@gavin.co.nz', 'password');

This line makes an ajax call, which is async, so the tests keep running, without waiting for the response from that ajax call. So our tests run fast, but this is not what we want in our full API test. This is not a Unit Test, it’s an integration test.

How does Jasmine help with Async tests?

Jasmine allows you a neat function on a spy, called ‘callFake()’. In your beforeEach, you can setup the functions to spyOn, but you can also add a callFake, which when that function is called, it also calls this new function. This allows you to inject a call into the end of the function, and in that, you can tell Jasmine the test is done, by calling done().

Note: This was not easy to figure out, there is a lot of documentation, but not too many people spelled it out like this. This is why I present on it, and this is why I’m sharing this blog post with you today.

Below is what it looks like. Inside the beforeEach, which accepts a function with the done object (this is what tells Jasmine its async), and then you setup your spies, with the callFake(), both spies waiting for a response, before calling done() so Jasmine knows the test is ready, and can process to the ‘it’ block. The last item in the beforeEach is the actual call you’re testing.

describe("Login API", function() {
   beforeEach(function( done ) {
       spyOn( window, "processLoginAjaxDone").and.callFake(
           function(){ done(); });
       spyOn( window, "processLoginAjaxFail").and.callFake(
           function(){ done(); });
       loginButtonEventHandlerProcess('gavin@gavin.co.nz', 'password');
   });
   it("should return a failing Ajax Response", function() {
       expect(processLoginAjaxDone).toHaveBeenCalled();
       expect(processLoginAjaxDone).toHaveBeenCalledWith('{"RESULT":400}');
       expect(processLoginAjaxFail).not.toHaveBeenCalled();
   });
});

 

So jasmine sets up the spies, calls your function, when the ajax async call returns, it calls one of the two functions you are spying on, when they are called, they also call done() and then the tests in the it block are run.

This solves the async problem, and when you know how to do it, its simple.
So now, there is no excuse.

Get out there, and start testing your API… on the client, with Jasmine, and on the server, with TestBox

Recent Entries

Hackers demand a ransom to restore data from my ColdFusion web applications!

Hackers demand a ransom to restore data from my ColdFusion web applications!

Hackers demand a ransom to restore data from my ColdFusion web applications!

Unfortunately, we often hear this message from clients who thought it would never happen to them... until it did. Some believed they could delay the expense of Implementing ColdFusion security best practices for one year, while others were tempted to put it off for just a few months. However, in today's rapidly evolving digital landscape, the security of web applications, including ColdFusio...

Cristobal Escobar
Cristobal Escobar
April 16, 2024
Ortus March Newsletter

Ortus March Newsletter

Welcome to Ortus Solutions’ monthly roundup, where we're thrilled to showcase cutting-edge advancements, product updates, and exciting events! Join us as we delve into the latest innovations shaping the future of technology.

Maria Jose Herrera
Maria Jose Herrera
April 01, 2024
Into the Box 2024 Last Early Bird Days!

Into the Box 2024 Last Early Bird Days!

Time is ticking, with less than 60 days remaining until the excitement of Into the Box 2024 unfolds! Don't let this golden opportunity slip away; our exclusive Early Bird Pricing is here for a limited time only, available until March 31st. Why wait? Secure your seat now and take advantage of this steal!

Maria Jose Herrera
Maria Jose Herrera
March 20, 2024