I have a file with two routes.
routes/index.js
const express = require('express')
const router = express.Router()
router.get('', (req, res, next) => {
try {
res.status(200).render('../views/')
} catch (error) {
next(error)
}
})
router.get('*', (req, res, next) => {
try {
res.status(404).render('../views/not-found')
} catch (error) {
next(error)
}
})
module.exports = router
I want to test the catch branches. One of the obvious problems is that I can't fake what the callback of router.get does, because then my test would be pointless, I would modify the very thing that I want to test.
I can send a Supertest request to these specific routes, but then I have no control over what happens. I want to avoid creating a hardcoded route, only so I can check whether the middleware is called by the next function. If I understand correctly, if I would have additional things happening in the try block (like a database query) than I could mock that to throw an error.
But I do not have any additional things happening there. Here is what I can not wrap my head around: if I mock what the server does, then I don't test what I already have but something else, so there is no point in doing that. Maybe I misunderstand how things work, but as far as I can see the only option would be to somehow mock what res.status or res.render does (stub them so they throw an error), so somehow mock what Supertest does, but I have no idea how to do that.
Any help would be greatly appreciated!
I have a file with two routes.
routes/index.js
const express = require('express')
const router = express.Router()
router.get('', (req, res, next) => {
try {
res.status(200).render('../views/')
} catch (error) {
next(error)
}
})
router.get('*', (req, res, next) => {
try {
res.status(404).render('../views/not-found')
} catch (error) {
next(error)
}
})
module.exports = router
I want to test the catch branches. One of the obvious problems is that I can't fake what the callback of router.get does, because then my test would be pointless, I would modify the very thing that I want to test.
I can send a Supertest request to these specific routes, but then I have no control over what happens. I want to avoid creating a hardcoded route, only so I can check whether the middleware is called by the next function. If I understand correctly, if I would have additional things happening in the try block (like a database query) than I could mock that to throw an error.
But I do not have any additional things happening there. Here is what I can not wrap my head around: if I mock what the server does, then I don't test what I already have but something else, so there is no point in doing that. Maybe I misunderstand how things work, but as far as I can see the only option would be to somehow mock what res.status or res.render does (stub them so they throw an error), so somehow mock what Supertest does, but I have no idea how to do that.
Any help would be greatly appreciated!
Share Improve this question edited Oct 6, 2020 at 16:24 szeb asked Sep 24, 2020 at 17:34 szebszeb 3964 silver badges26 bronze badges 2- What is it really that you want to assert with your test? That the middleware is called in case of an exception? – Christian Commented Sep 24, 2020 at 18:52
- 1 Yes. I think that whenever an error is thrown and there is an error handling middleware, the error handling middleware will catch it, so this is not the only way that it could be triggered. Also, maybe somehow I could just check whether the error handling middleware was called once, although it would be nice to manually test whether the test framework will run the line in catch. I know that it doesn't really have a practical purpose, but it would be nice how to do it anyway if a similar problem pops up – szeb Commented Sep 24, 2020 at 19:09
1 Answer
Reset to default 6unit test solution:
route.js
:
const express = require('express');
const router = express.Router();
router.get('', (req, res, next) => {
try {
res.status(200).render('../views/');
} catch (error) {
next(error);
}
});
router.get('*', (req, res, next) => {
try {
res.status(404).render('../views/not-found');
} catch (error) {
next(error);
}
});
module.exports = router;
route.test.js
:
describe('64051580', () => {
afterEach(() => {
jest.resetModules();
jest.restoreAllMocks();
});
it('should render views', () => {
const express = require('express');
const mRouter = { get: jest.fn() };
jest.spyOn(express, 'Router').mockImplementationOnce(() => mRouter);
const mReq = {};
const mRes = { status: jest.fn().mockReturnThis(), render: jest.fn() };
const mNext = jest.fn();
mRouter.get.mockImplementation((path, callback) => {
if (path === '') {
callback(mReq, mRes, mNext);
}
});
require('./route');
expect(mRes.status).toBeCalledWith(200);
expect(mRes.render).toBeCalledWith('../views/');
});
it('should handle error', () => {
const express = require('express');
const mRouter = { get: jest.fn() };
jest.spyOn(express, 'Router').mockImplementationOnce(() => mRouter);
const mReq = {};
const mErr = new Error('parse');
const mRes = {
status: jest.fn().mockReturnThis(),
render: jest.fn().mockImplementationOnce(() => {
throw mErr;
}),
};
const mNext = jest.fn();
mRouter.get.mockImplementation((path, callback) => {
if (path === '') {
callback(mReq, mRes, mNext);
}
});
require('./route');
expect(mNext).toBeCalledWith(mErr);
});
it('should render 404 not found view', () => {
const express = require('express');
const mRouter = { get: jest.fn() };
jest.spyOn(express, 'Router').mockImplementationOnce(() => mRouter);
const mReq = {};
const mRes = { status: jest.fn().mockReturnThis(), render: jest.fn() };
const mNext = jest.fn();
mRouter.get.mockImplementation((path, callback) => {
if (path === '*') {
callback(mReq, mRes, mNext);
}
});
require('./route');
expect(mRes.status).toBeCalledWith(404);
expect(mRes.render).toBeCalledWith('../views/not-found');
});
});
unit test result with coverage report:
PASS src/stackoverflow/64051580/route.test.js
64051580
✓ should render views (656ms)
✓ should handle error (17ms)
✓ should render 404 not found view (16ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 90.91 | 100 | 100 | 90.91 | |
route.js | 90.91 | 100 | 100 | 90.91 | 16 |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 4.28s, estimated 10s
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744363599a4570589.html
评论列表(0条)