NOTE: This article assumes that node and npm are already setup and you are using this on an existing project. The demo project can be found on github.com at https://github.com/rclanan/frisby-demo

A colleague of mine, Jamie Kurtz, recently introduced me to a cool little tool called frisby.js. To quote frisby.js, Frisby is a REST API testing framework built on node.js and Jasmine that makes testing API endpoints easy, fast and fun.

After using it for a little over a week to do some basic testing of a new REST web API that we were working on, I would have to agree that it is very easy and fast to pick up and use. As such, I just wanted to do a quick write up on it to help demo it to other developers. I created a lightning talk demo to present at one of our team lunches, and this post is an extension of that talk.

First steps, to install frisby.js, add it to your node.js project by running: npm install --save-dev frisby

We will also need jasmine-node, which is used to run the actual frisby.js test. To install jasmine-node run: npm install -g jasmine-node

To make running the test easier, I would also recommend adding a new script to the package.json file. Label the script test and set the value to jasmine-node .. The period, in this case, is the path of where your test files are stored. Since I am using the demo project, my tests are directly on the root of the project.

"scripts": {
"test": "jasmine-node ."
},

I also like to create another script called test:live and set the value of jasmine-node . --autotest, which allows for the automatic execution of the specs after changes in the specs. If you want to run after changes outside of the specs, you can add --watch.

"scripts": {
"test": "jasmine-node .",
"test:live": "jasmine-node . --autotest"
},

With that in place, we now can run our test by either using npm test or npm run test:live.

Now onto the test themselves! Since I am just trying to demo frisby.js and not how to develop a full-blown REST API, I am going to use a handy site called JSONPlaceholder. JSONPlaceHolder, is a fake online REST API for testing and prototyping.

For the first test, we are going just to test to make sure the status code is what we expect, and the header contains the proper content-type we expect to get back on the response. I am going to make a GET request to /posts, which should return JSON data and a status code of 200.

To start with, we need to import the frisby library into our test file. In the demo, this file is first-spec.js.

var frisby = require('frisby');

Now to create the actual test itself. First, we use the create method to name the test, then since this is a GET request, we will use the get method and pass in the URL of where we are issuing the command to. After that, we toss the frisby, I mean test!

frisby.create('JSONPlaceholder - Posts API test: GET /posts')
.get('http://jsonplaceholder.typicode.com/posts')
.toss();

This will create our test for us but doesn’t do much good without a few extra methods, which in this case, are referred to as expectations via the frisby.js documentation. In our first test, I stated that we are going to test the status code and the content header, so we need to add the expectStatus and expectHeader or expectHeaderContains. I am going to use expectHeaderContains as it’s the less strict version of expectHeader, but either method should work.

frisby.create('JSONPlaceholder - Posts API test: GET /posts')
.get('http://jsonplaceholder.typicode.com/posts')
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.toss();

With the first test complete, if you haven’t already started test:live then from a command line, issue the following: npm test

The output should look similar to this:

.

Finished in 0.906 seconds
1 test, 2 assertions, 0 failures, 0 skipped

Since the next couple of tests, all follow the same format, I am going to bundle up a few of the steps and just show/talk about the test itself.

For the next test, I am going to test the results of the same GET request that we used in the first test. This time though, I am going to add expectJSONTypes that will test that the results data type match what we expect to get back. The JSON data set contains an array of items with each item having the structure of:

{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

For testing every item in the array with the above structure, our expectJSONTypes will look like:

.expectJSONTypes('*', {
userId: Number,
id: Number,
title: String,
body: String
})

If you notice the asterisk, that denotes that we want to test the elements of the entire array. To test a single item in the array, we can use a question mark instead.

.expectJSONTypes('?', {
userId: Number,
id: Number,
title: String,
body: String
})

Now that we have tested the status code, the content header, the data types, let’s create a new test that will test the actual JSON data itself. For that, I am going to use a GET request still but change URL to just return the first post with an id of 1. To test the actual JSON data that is returned, we use expectJSON.

frisby.create('JSONPlaceholder - Posts API test: GET /posts/1')
.get('http://jsonplaceholder.typicode.com/posts/1')
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.expectJSONTypes({
userId: Number,
id: Number,
title: String,
body: String
})
.expectJSON({
userId: 1,
id: 1,
title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
})
.toss();

The other way we could have achieved the same result would be to chain the test together. To call additional test or perform additional logic we can utilize the “Helper” afterJSON:

frisby.create('JSONPlaceholder - Posts API test: GET /posts')
.get('http://jsonplaceholder.typicode.com/posts')
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.expectJSONTypes('*', {
userId: Number,
id: Number,
title: String,
body: String
})
.afterJSON(function(json) {
var firstPost = json[0];

frisby.create('JSONPlaceholder - Posts API test: GET /posts/1')
.get('http://jsonplaceholder.typicode.com/posts/' + firstPost.id)
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.expectJSONTypes({
userId: Number,
id: Number,
title: String,
body: String
})
.expectJSON({
userId: 1,
id: 1,
title: "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
body: "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
})
.toss();

})
.toss();

Using the above methods should allow you to get started writing some quick test for your REST API. So far, I like the simplicity of frisby.js. If you know of any other cool libraries to help improve unit testing and overall code quality, hit me up as I am always looking for new tools/ideas on how to improve my code quality and overall workflow!

Extra – Debugging Information

Just a quick note about another method that I find to be very useful when generating these test is the inspectJSON method. Before I reread the documentation, I was utilizing the afterJSON method to console.log the JSON data that was returned out to the console so I could verify what I was testing. The inspectJSON method used the node.js pretty print utility method util.inspect to provide a colored console output. Frisby.js also provides a inspectBody method that will just dump the raw parsed/marked up output to the screen as well.

As always, until next time…