Integration testing is a critical part of any QA effort. It can be used as a final check before any backend API deployment and give confidence to the development team that the deploy is safe.
We’ll work through a simple API test written in NodeJS and use a couple of popular testing frameworks:
chai-http - extensions for making HTTP requests to APIs
For our example we’ll use an existing public API - the Yahoo Weather API. We’ll build two tests, one positive and one negative.
Create the project
Let’s get the project started. Assuming you already have npm installed, in a new directory, initialize the project and install the relevant npm modules:
1
2
3
$ mkdir sample-yahoo-api-tests
$ npm init
$ npm install --save-dev mocha chai chai-http
This creates a package.json file that contains the package dependencies mentioned above. Let’s make a few changes to this as so (don’t change the versiopn numbers after each package in the devDependencies section as they will probably be different in your case):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"name": "sample-yahoo-api-tests",
"version": "1.0.0",
"description": "Yahoo Weather API tests",
"main": "index.js",
"dependencies": {
},
"devDependencies": {
"chai": "^3.5.0",
"chai-http": "^3.0.0",
"mocha": "^3.1.2"
},
"author": "",
"license": "ISC"
}
Mocha gives us a standard and simple format of writing tests. Generally we group tests into individual test files. Each test file then has a smaller group and then the tests within.
Each file has a describe…it structure as so:
1
2
3
describe("Some feature or API")
it("Should or should not do something")
it("Should or should not do something else")
Our general structure will be:
1
2
3
4
5
6
7
8
9
describe('Yahoo Weather API', function() {
it("returns a result for Santa Monica, CA", function() {
// Test code here
});
it("returns null results for invalid location", function() {
// Test code here
});
});
chai-http allows us to easily make requests to an HTTP endpoint and handle the response. The general format is:
1
2
3
4
5
chai.request(server)
.get(path)
.then(function(res) {
// Test code here
});
The Yahoo endpoint we’re going to test is https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22Santa%20Monica%2C%20CA%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys which will return us basic weather information for Santa Monica, CA:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"query": {
"count": 1,
"created": "2016-11-03T05:18:01Z",
"lang": "en-US",
"results": {
"channel": {
"item": {
"condition": {
"code": "31",
"date": "Wed, 02 Nov 2016 09:00 PM PDT",
"temp": "70",
"text": "Clear"
}
}
}
}
}
}
Building the first (positive) test
Putting this all together, here’s our first test that we’ll create in test/yahoo-weather.spec.js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var chai = require('chai');
var chaiHttp = require('chai-http');
var expect = chai.expect;
// Tell chai to use chai-http
chai.use(chaiHttp);
describe('Yahoo Weather API', function() {
it("returns a result for Santa Monica, CA", function() {
Note that there are actually 4 assertion tests here:
1
expect(res).to.have.status(200);
This ensures that the HTTP response code for this request is 200, which is a general success response. If the server returns some error, we’ll get a failure in our tests here.
As you can see, we now have a simple working API test! Let’s go ahead and add our second test that ensure we get a null response for a city that doesn’t exist:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
var chai = require('chai');
var chaiHttp = require('chai-http');
var expect = chai.expect;
// Tell chai to use chai-http
chai.use(chaiHttp);
describe('Yahoo Weather API', function() {
it("returns a result for Santa Monica, CA", function() {
Our second test is similar to the first, except we’re passing in a city name that we know doesn’t exist (‘AAAAAAAAAAAA’) and expecting the results to be null. Let’s run this and make sure it works:
✓ returns null results for invalid location (207ms)
2 passing (488ms)
Tidy up
Let’s do some tidying up. Firstly, typing in the full test command is long-winded. We’ll create a script in package.json to make it easier to run. Add the scripts section into your package.json file:
Next, let’s clear up our code a little. We’ll add a helper file that’ll clean up the API URL that we’re calling for both tests. Create test/yahoo-helpers.js and add this as content: