Reputation: 21
I'm attempting to write some unit tests for API endpoints, and decided on JavaScript Express w/ Supertest. I've got the basic downs, but running into issues checking the response for a specific field. I want to parse the body and check if an expected field returns and has the correct value. Most everything I've seen online uses this method, but when I try it always passes, even when I enter values I know don't exist in the JSON. Any advice? Here is my code snippet:
describe('GET category', function () {
it('response w/ only injury returned', function () {
request('endpoint')
.get('path')
.set('header', 'token')
.expect(200)
.then(response => {
console.assert(response.body, "Baseball")
})
})
});
I have also tried changing the .then to .expect, with same results. If I do response.body.specificFieldinBody I get similar results. Any help?
Upvotes: 2
Views: 1446
Reputation: 57344
I see three issues:
console.assert(response.body, "Baseball")
only checks whether response.body
is truthy. "Baseball"
is just the message that prints if it isn't (i.e. Assertion failed: Baseball
). You may be looking for
console.assert(response.body.Baseball, "body.Baseball should be defined")
or you may want to assert that the value for a particular key equals "Baseball"
; something like
console.assert(response.body.injury === "Baseball", "body.injury === 'Baseball'")
console.assert
just logs the failure to the console, which likely won't be picked up by whatever testing library you're using (Mocha, Jest). I suggest using an assertion library like Chai, Jest's built-in assertions, or at least Node's native assert
so the test will show as a failure.
request('endpoint')
returns a promise. If the test suite isn't appraised of the asynchronous nature of the test, it'll happily give you an instant pass without actually running any assertions. Use return request('endpoint')
to ensure that the test suite awaits for the promise chain to resolve and detects any assertions.
Marking your test async
helps reduce the footgun factor and is generally cleaner than .then()
or callbacks (less nesting). Here's a complete example you can run with npx mocha server.test.js
.
server.test.js
:
const assert = require("assert");
const request = require("supertest");
const app = require("./server");
describe("GET category", () => {
it("response with only injury returned", async () => {
const response = await request(app).get("/path");
assert(response.status === 200);
assert(response.body.injury === "Baseball");
});
// ... or use supertest's assertions:
it("response with only injury returned (alternate approach)", () => {
return request(app)
.get("/path")
.expect(200, {injury: "Baseball"});
});
});
server.js
:
const express = require("express");
const app = express();
app.get("/path", (req, res) => res.json({injury: "Baseball"}));
module.exports = app;
package.json
:
{
"dependencies": {
"express": "^4.18.3"
},
"devDependencies": {
"mocha": "^10.3.0",
"supertest": "^6.3.4"
}
}
Upvotes: 0
Reputation: 16157
You can do with your way - use .then
syntax, but I think use Supertest
assertion syntax will be good.
This mean, use response.body.should.have.property("Baseball");
instead of console.assert(response.body, "Baseball")
(Baseball
is your special field).
Or, My suggestion is creating a re-use code: Put a assertion callback function to a next expects
section.
const isIncludeField = function (fieldName) {
return function (res) {
res.body.should.have.property(fieldName);
};
}
describe('GET category', function () {
it('response w/ only injury returned', function () {
request('endpoint')
.get('path')
.set('header', 'token')
.expect(200)
.expect(isIncludeField('Baseball')) //
.end(done); // call done callback
})
});
Upvotes: 1