0

I am busy building functional tests for an existing nodejs api I wrote. I am using mocha and expect.js.

One test that is failing is when I want to do a negative test for the existence of a url parameter. What I want is to send a message back to the the consumer of the service if the param is missing.

Currently the positive test I have works:

var request = require('request');

it('get a specific user from the api', function (done) {
    request.get('http://localhost:8080/api/v1/user/123', function (error, response, body) { ... });
});

However, the following does not work and all I get is a timeout:

it('should return a 400 message if UserId is not supplied stating that "UserId expected"', function(done) {
    request.get('http://localhost:8080/api/v1/user/', function (error, response, body) { 
        if (!error && response.statusCode == 400) {
            expect(body).to.be.equal('UserId expected');
            done();
        }
    });
});

Both the above tests are testing this endpoint:

app.get('/api/v1/user/:userid', function (req, res) {
    if(!req.params.userid) {
        return res.status(400).json('UserId expected');
    }

    ... get the user and return it with status 200 ...
});

However, as stated before, the first test is successful while the second test times out.

Update 1: Additionally, I am getting the following output:

GET /api/v1/user/123 200 2.905 ms - 274
GET /api/v1/user/ - - ms - -

Update 2: So adding the following code solves the problem, but doesn't really solve the problem:

app.get('/api/v1/user', function (req, res) {
    return res.status(400).json('UserId expected');
});

Obviously I don't want a rather redundant piece of code sitting around. I am baffled as to why I cannot enter the 'api/v1/user/:userid' endpoint and just test for the existence of :userid in there? It's as if nodejs is requiring the existence of :userid, otherwise the endpoint does not exist. Is this correct?

What am I missing?

Ebbs
  • 1,030
  • 3
  • 20
  • 38
  • Do you no if there comes something back from the server? Can you just add some console.log/breakpoints on both sites to see where it get stuckt? How do you know that your first test succeed there no assertions or did you just chopped it off? – Sprotte Jan 27 '16 at 22:12
  • I have added console.log's in both the server and the test and I do not get a response from the server. I think the request must be getting stuck server side, but I cannot tell where as I have a console.log on the very first line of the endpoint on the server, but it never gets hit. – Ebbs Jan 28 '16 at 19:54

2 Answers2

0

According to mocha documentation the done callback must always be called, also in case of errors. In fact it accepts an error. So I think that you must rewrite your code with:

it('should return a 400 message if UserId is not supplied stating that "UserId expected"', function(done) {
    request.get('http://localhost:8080/api/v1/user/', function (error, response, body) {
        if (error) return done(error);
        if (response.statusCode != 400) return done(new Error("Not 400"));

        expect(body).to.be.equal('UserId expected');
        done();
    });
});
Davide Icardi
  • 11,919
  • 8
  • 56
  • 77
  • You are right and I rewrote it the way you described, also I added console.log's inside the callback in request.get. However, I never get a result from those console.log's, still just the timeout. This leads me to believe there is something I am not handling serverside, but I am never getting a response from the console.log I put on the very first line of the endpoint.... – Ebbs Jan 28 '16 at 19:36
0

So I did some more investigation and asked another question regarding this issue here.

In the end the issue was that I didn't fully understand the express framework. Basically what I alluded to in Update 2 of my question is the route I will need to follow and specify a route where no param is expected, but return the error message I am expecting in that case.

The problem I have with this approach is that in some instances one might want to use more than one parameter in the ur. However, this will mean the permutations to cater for each scenario where a parameter is undefined gets a bit daunting. (2 params will mean 4 combinations, 3 will mean 9 etc.) This will be a maintenance nightmare!

My approach from now on will be to rather follow an approach where any info I want to pass to the server will be sent via JSON in the body from of each request. This will allow me to keep to one single route.

Community
  • 1
  • 1
Ebbs
  • 1,030
  • 3
  • 20
  • 38