Been working on this for days now. Finally breaking over and asking for help.
When I have the server running and make API calls, things work as expected.
Now I am trying to unit test the controller and running into issues. Hoping for some clarification as I am obviously missing something vital.
classCodesController.js (base minimum code. I have commented out everything but this in my testing without joy)
import { classCodeModel } from '../models/classCodeModel.js';
import { asyncHandler } from '../utils/asyncHandler.js';
const getAll = async (req, res, next) => {
const record_set = [];
res.status(400).json({
status: 'success',
length: record_set.length,
data: record_set
});
};
export {
getAll
};
classCodesController.test.js
import assert from 'node:assert/strict';
import { describe, it, mock } from 'node:test';
import mockHttp from 'node-mocks-http';
import { getAll } from '../../src/controllers/classCodeControllerv1.js';
import { classCodeModel } from '../../src/models/classCodeModel.js';
describe('getAll: return JSON', () => {
it('should return array of two records as JSON', { timeout: 5000 }, async () => {
const req = mockHttp.createRequest();
const res = mockHttp.createResponse();
const next = mock.fn();
await getAll(req, res, next);
assert.deepStrictEqual(res.statusCode, 400);
assert.deepStrictEqual(res.json(body), { status: 'success', length: 0, data: [] });
});
});
When called, the status code does not change and the json is not returned.
I have tried passing my own res object which worked when I unit tested middleware modules.
const res = {
body: '',
data: {},
message: undefined,
statusCode: 100, // noramlly defaults to 200
statusText: '', // normally 'OK'
headers: {},
config: {},
reqeust: {},
send: mock.fn(),
status: mock.fn(c => {
this.statusCode = c;
return this;
}),
json: mock.fn(d => {
this.message = d;
console.log('json d: ', d);
})
}
The console.log in json function outputs the controller submitted data, but message is still undefined (TypeError: Cannot set properties of undefined (setting 'message')) when it gets to the test and the statusCode has not changed.
All help is appreciated. Thanks in advance.
From the documentation, you should use res._getJSONData()
to get the response JSON data. Below is a working example:
getAll.js
:
const getAll = async (req, res) => {
const record_set = [];
res.status(400).json({
status: 'success',
length: record_set.length,
data: record_set,
});
};
export { getAll };
getAll.test.js
:
import assert from 'node:assert/strict';
import { describe, it, mock } from 'node:test';
import mockHttp from 'node-mocks-http';
import { getAll } from './getAll.js';
describe('getAll: return JSON', () => {
it('should return array of two records as JSON', async () => {
const req = mockHttp.createRequest();
const res = mockHttp.createResponse();
const next = mock.fn();
await getAll(req, res, next);
assert.deepStrictEqual(res.statusCode, 400);
assert.deepStrictEqual(res._getJSONData(), { status: 'success', length: 0, data: [] });
});
});
Test result:
$ node --test ./getAll.test.js
▶ getAll: return JSON
✔ should return array of two records as JSON (1.215ms)
▶ getAll: return JSON (2.3065ms)
ℹ tests 1
ℹ suites 1
ℹ pass 1
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 80.1445
package.json
:
{
"name": "77646756",
"version": "1.0.0",
"type": "module",
"devDependencies": {
"node-mocks-http": "^1.14.0"
}
}
Node version:
$ nvm ls
* 21.4.0 (Currently using 64-bit executable)
18.19.0
16.20.2