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

The Hidden Costs of In-House Database Management

The Hidden Costs of In-House Database Management

The Hidden Costs of In-House Database Management


Opting for in-house database management involves more than just a salary. Here are some often-overlooked costs associated with maintaining your own DBA team.



1. High Salaries and Benefits


Hiring skilled DBAs is expensive. According to industry reports, the average salary of a DBA in the U.S. can range from $85,000 to over $130,000 per year, depending on experience and expertise. When you add ...

Cristobal Escobar
Cristobal Escobar
November 20, 2024
5 Signs It’s Time to Modernize Your ColdFusion / CFML Application

5 Signs It’s Time to Modernize Your ColdFusion / CFML Application

ColdFusion has long been a reliable platform for building web applications, but like any technology, it requires maintenance and modernization over time. Whether you're using Lucee or Adobe ColdFusion, it’s critical to recognize the signs that your application is no longer meeting today’s standards in performance, security, and scalability. Let’s explore five clear indicators that it’s time to modernize your ColdFusion application and how ColdFusion consulting can help breathe new life into y...

Cristobal Escobar
Cristobal Escobar
November 19, 2024
ColdBox Free Tip 5 - Building Named Routes with a Struct

ColdBox Free Tip 5 - Building Named Routes with a Struct

**Did you know ColdBox provides flexible ways to build routes using structs?** In this tip, we’ll cover how to use the `event.buildLink()` and `event.route()` methods for named routes, a feature that’s especially handy when working with dynamic URLs.

Maria Jose Herrera
Maria Jose Herrera
November 19, 2024