Testing Routes With Mocha and Chai

John | April 15, 2019

Testing Routes with Mocha and Chai

While working on a restful api built with express I was trying to find an easy way to test my routes along with my unit tests using chai so I came up with a simple typescript class to fake http requests and responses so that I can verify that the request status and response body are set correctly and figured I’d share it here.

It’s really simple so I’m just going to throw down the code for the class all at once and then explain how it works:

export default class FakeHttp {

    public req;

    public res;
    
    public response;

    constructor(){
        this.init();
    }

    public reset(){
        this.init();
    }

    private init(){
        this.req = {
            params: {},
            body: {},
        };
        this.response = {};
        this.res = {
            send: (obj: any) => {
                this.response.body = obj;
            },
            status: (code: number) => {
                this.response.status = code;
                return this.res;
            }
        }
    }
}

What we have here is a class that has three public variables: req, res, and response. The req and res variable are for representing the http request and response objects while response is going to contain the the response values. I have an init function that sets the initial values for the variables. The req variable is just set to contain two empty objects params and body, no surprise here, these will act as the http request parameters and the body of the request. Then the res variable is a little bit more complicated. We initialize it to have two variables, send and status that are set too anonymous functions. The send function takes and object and then set the response.body property to the passed in object. The status function takes a number and sets the response.status to the passed in code. Init is called in both he constructor, to set the initial values, and in the rest function, to clear out values left over from a previous test. And that’s it.

Now we need some routes to test so we’ll just set up a simple post route:

export default class TestRoutes {

    static testPost(req, res){
        let to = req.params.to;
        let from = req.params.from;
        let message = req.body.message;
        res.status(200).send({
            to: to,
            from: from,
            message: message,
        })
    }
}

I have this post route just so that I can show how our class works for both request parameters and body. So our testPost route takes two parameters “to” and “from” and then a body with the property “message” and then takes those values and responds with a message object.

And no we’ll test our route using mocha, chai, and our new FakeHttp class:

describe('TestRoutes', () => {
    
    let http: FakeHttp;
    
    before(() => {
        http = new FakeHttp();
    });

    beforeEach(() => {
        http.reset();
    });

    it('.postTest takes to and from parameters and then a message body and responds with a message object', () => {
        http.req.params["to"] = "Chris";
        http.req.params["from"] = "John";
        http.req.body = {message: "Hey Chris"};
        TestRoutes.testPost(http.req, http.res);
        expect(http.response.status).to.equal(200);
        expect(http.response.body).to.deep.equal({to: "Chris", from: "John", message: "Hey Chris"});
    });

});

So you can see here that I have a FakeHttp variable “http” that I initialize in the before hook and that I called http.reset() in the beforeEach hook in order to reset all our values between hooks. Then inside the test I set the request parameters and body. I then call the route passing it our http req and res objects and finally I check the response object to verify that the request was responded to with the expected status and body.

So does it work?

YUP!

By: John