在这种情况下,如何使用Jest测试Express路由器的捕获分支?

问题描述

我有两个路由的文件

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('*',next) => {
  try {
    res.status(404).render('../views/not-found')
  } catch (error) {
    next(error)
  }  
})

module.exports = router

我想测试捕获分支。显而易见的问题之一是,我无法伪造router.get的回调所做的事情,因为这样我的测试将毫无意义,我将修改我想测试的东西。

我可以向这些特定的路由发送“超级测试”请求,但随后我无法控制发生的情况。我只想避免创建硬编码的路由,这样只能检查下一个函数是否调用了中间件。如果我理解正确,那么在try块中是否还有其他事情(例如数据库查询)发生,而不是我可以模拟那个来引发错误

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

任何帮助将不胜感激!

解决方法

单元测试解决方案:

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('*',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','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,mNext);
      }
    });
    require('./route');
    expect(mNext).toBeCalledWith(mErr);
  });

  it('should render 404 not found view',callback) => {
      if (path === '*') {
        callback(mReq,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 total
Tests:       3 passed,3 total
Snapshots:   0 total
Time:        4.28s,estimated 10s

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...