如何通过调用 next(error) 来测试 express 中间件抛出错误

How to test that express middleware throws an error by calling next(error)

我试图通过存根 next() 来捕获错误,但它失败了。

函数如下

async getUser (req, res, next) {
  try {
    if (!req.user) {
      throw new CustomError('找不到使用者', 404)
    } else {
      // do something
    }
  } catch (err) {
    next(err)
  }
}

和单元测试部分

it('no user data => Error 404', async () => {
  const res = mockedResponse()
  const next = sinon.stub()
  await getUser({}, res, next)
  expect(next.getCall(0).args[0]).to.deep.equal(new CustomError('cannnot find user', 404))
})

然而测试结果表明

AssertionError: expected [Error: cannnot find user] to deeply equal [Error: cannnot find user]

是否有更好的方法来捕获函数抛出的 CustomError?

deep-eql 算法不会对错误进行深度相等。参见 https://github.com/chaijs/chai/issues/1065#issuecomment-337857345

解决方法如下:

index.js:

const CustomError = require('./customError');

const controller = {
  async getUser(req, res, next) {
    try {
      if (!req.user) {
        throw new CustomError('找不到使用者', 404);
      } else {
        // do something
      }
    } catch (err) {
      next(err);
    }
  },
};

module.exports = controller;

customError.js:

class CustomError extends Error {
  constructor(message, code) {
    super(message);
    this.code = code;
  }
}

module.exports = CustomError;

index.test.js:

const controller = require('./');
const CustomError = require('./customError');
const sinon = require('sinon');
const { expect } = require('chai');

describe('61879445', () => {
  it('should throw error if user not found', async () => {
    const mNext = sinon.stub();
    const mReq = {};
    const mRes = {};
    await controller.getUser(mReq, mRes, mNext);
    // chai way
    expect(mNext.getCall(0).args[0]).to.be.an.instanceof(CustomError);
    expect(mNext.getCall(0).args[0]).to.have.property('message', '找不到使用者');
    expect(mNext.getCall(0).args[0]).to.have.property('code', 404);
    // sinon way
    sinon.assert.calledWith(
      mNext,
      sinon.match
        .instanceOf(CustomError)
        .and(sinon.match.has('message', '找不到使用者'))
        .and(sinon.match.has('code', 404)),
    );
  });
});

带有覆盖率报告的单元测试结果:

  61879445
    ✓ should throw error if user not found


  1 passing (15ms)

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------|---------|----------|---------|---------|-------------------
All files       |     100 |       50 |     100 |     100 |                   
 customError.js |     100 |      100 |     100 |     100 |                   
 index.js       |     100 |       50 |     100 |     100 | 6                 
----------------|---------|----------|---------|---------|-------------------