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

Add Your Comment

Recent Entries

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
Ortus February Newsletter 2024

Ortus February Newsletter 2024

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
March 06, 2024
Unveiling the Future of CFML Development - 3rd Round of Sessions

Unveiling the Future of CFML Development - 3rd Round of Sessions

Welcome back to our journey into the future of CFML development! As excitement continues to build for Into the Box 2024, we're thrilled to bring you the latest updates on what promises to be a transformative event. Continuing our blog post series, let's delve deeper into the third wave of session releases and discover the key surprises awaiting attendees. Learn More

Maria Jose Herrera
Maria Jose Herrera
March 01, 2024