如何使用 Jest 在这种情况下测试 Express router catch 分支?

我有一个包含两条路线的文件。


路线/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

我想测试 catch 分支。一个明显的问题是我无法伪造 router.get 的回调所做的事情,因为那样我的测试将毫无意义,我会修改我想要测试的东西。


我可以向这些特定路由发送超测请求,但我无法控制发生的情况。我想避免创建硬编码路由,这样我就可以检查下一个函数是否调用了中间件。如果我理解正确的话,如果我在 try 块中发生其他事情(比如数据库查询),那么我可以模拟它来抛出错误。


但是我那里没有发生任何其他事情。这是我无法解决的问题:如果我模拟服务器的功能,那么我不会测试我已经拥有的东西,而是测试其他东西,所以这样做没有意义。也许我误解了事情是如何工作的,但据我所知,唯一的选择是以某种方式模拟 res.status 或 res.render 所做的事情(存根以便它们抛出错误),所以以某种方式模拟 Supertest 所做的事情,但我不知道该怎么做。


任何帮助将不胜感激!


烙印99
浏览 87回答 1
1回答

至尊宝的传说

单元测试解决方案: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');  });});带有覆盖率报告的单元测试结果: 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 totalTests:       3 passed, 3 totalSnapshots:   0 totalTime:        4.28s, estimated 10s
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript