首页 > 解决方案 > 使用 mocha、chai、chai-http 和 sinon 在 Express API 上测试 try-catch

问题描述

我有一个使用 Express 创建的 API 应用程序,在控制器上具有此功能

/** UserController.ts */ 
--------------------------

  public static get = async (req: Request, res: Response): Promise<void> => {
    try {
      const user = await UserModel.findById(<<id>>)
 
      if (user) {
        res.status(200).json(<I200Response>{ msg: 'user data', data: user })
      }
    } catch (e) {
      res.status(500).json(<I500Response>{ error: e.message })
    }
  }

我正在尝试使用 sinon 测试“catch block”的工作,但我不明白。这是我尝试的数百个测试之一:

/** User.specs.ts */
---------------------

  it('Internal server error', async () => {
    const stubReq = chai.request(BASE)
    const stub = sinon.stub(stubReq, 'get').throws(new Error('stub: Internal server error'))

    const r = await request.get(API.info).set('Authorization', userToken)
    stub.reset()

    expect(r).to.have.status(500)
    return expect(r.body).to.have.property('error').that.is.equal('stub: Internal server error')
  })

但是响应的状态为 200 并获取所需的数据。

任何想法?

标签: expresstry-catchintegration-testingsinonchai-http

解决方案


您应该UserModel.findById使用sinon.js.

例如

UserController.ts

import { Request, Response } from 'express';
import { UserModel } from './UserModel';

type I500Response = any;
type I200Response = any;

export class UserController {
  public static get = async (req: Request, res: Response): Promise<void> => {
    try {
      const user = await UserModel.findById(1);

      if (user) {
        res.status(200).json(<I200Response>{ msg: 'user data', data: user });
      }
    } catch (e) {
      res.status(500).json(<I500Response>{ error: e.message });
    }
  };
}

UserModel.ts

export class UserModel {
  public static findById(id: number) {
    return { id, name: 'real username' };
  }
}

app.ts

import express from 'express';
import { UserController } from './UserController';

const app = express();
const port = 3000;
app.get('/user/:id', UserController.get);

export { app };

app.test.ts

import chai, { expect } from 'chai';
import chaiHttp from 'chai-http';
import { app } from './app';
import { UserModel } from './UserModel';
import sinon from 'sinon';

chai.use(chaiHttp);

describe('62502383', () => {
  it('should pass', (done) => {
    const mError = new Error('stub: Internal server error');
    const findByIdStub = sinon.stub(UserModel, 'findById').rejects(mError);
    chai
      .request(app)
      .get('/user/1')
      .end((err, res) => {
        sinon.assert.calledWith(findByIdStub, 1);
        expect(res).to.have.status(500);
        expect(err).to.be.null;
        expect(res.body.error).to.be.equal('stub: Internal server error');
        done();
      });
  });
});

集成测试结果:

  62502383
    ✓ should pass


  1 passing (31ms)

-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   82.35 |        0 |   66.67 |   81.25 |                   
 UserController.ts |   77.78 |        0 |     100 |      75 | 12-13             
 UserModel.ts      |      50 |      100 |       0 |      50 | 3                 
 app.ts            |     100 |      100 |     100 |     100 |                   
-------------------|---------|----------|---------|---------|-------------------

推荐阅读