如何在集成测试中向Sinon存入服务?

问题描述 投票:0回答:1

我正在尝试为我的api做一些集成测试。

我的API的结构类似于:

app -> routes -> controllers -> services

因为我已经有单元测试,所以我的想法只是测试所有组件是否以正确的方式连接。

因此,我的想法是与Sinon一起为该服务创建的存根,并且仅使用supertest检查控制器的响应。

[当我运行一个测试时,一切正常。问题是,当我为不同的控制器运行多个单元测试时,存根在第二次运行中不起作用。

我认为是因为该应用程序已经作为模块保存在缓存中,所以sinon无法对服务进行存根。

我的代码的一些示例:

controller.js

const httpStatus = require('http-status');
const { service } = require('../services/croupier');

/**
 * Execute lambda tasks for candidates
 * @public
 */
exports.task = async (req, res, next) => {
  try {
    const result = await service({
      body: req.body,
      authorizer: req.authorizer
    });
    console.log('res', result);

    res.status(httpStatus.OK).json(result);
  } catch (error) {
    next(error);
  }
};

foo.integration.test.js

const request = require('supertest');
const httpStatus = require('http-status');
const sinon = require('sinon');
const mongoose = require('../../../database');

const deleteModule = module => delete require.cache[require.resolve(module)];

const requireUncached = module => {
  deleteModule(module);
  return require(module);
};

describe('Foo - Integration Test', async () => {
  describe('POST /v1/foo', () => {
    const fooService = require('../../services/foo');
    const stub = sinon.stub(fooService, 'service');
    let db;
    before(async () => {
      db = await mongoose.connect();
    });

    afterEach(async () => {
      sinon.restore();
    });

    after(async () => {
      await db.close();
    });

    it('the api should response successfully', async () => {
      stub.returns({});
      const payload = { task: 'task', payload: [{ pathParameters: {}, body: {} }] };
      const app = requireUncached('../../../app');
      await request(app)
        .post('/api/foo')
        .send(payload)
        .expect(httpStatus.OK);
    });

    it('the api should response with an error', async () => {
      stub.throwsException();
      const payload = { task: 'task', payload: [{ pathParameters: {}, body: {} }] };
      const app = requireUncached('../../../app');
      await request(app)
        .post('/api/foo')
        .send(payload)
        .expect(httpStatus.INTERNAL_SERVER_ERROR);
    });
  });
});

其他集成测试具有相同的结构。我也尝试使用proxyquire,但没有用。

此外,我也尝试成功删除de app.js的缓存。

有什么想法吗?

node.js express integration-testing sinon supertest
1个回答
0
投票

上下文:集成测试。

  1. 我同意您的想法:“测试所有组件是否以正确的方式连接”。然后,您需要的是spy,而不是存根。在有情况的情况下,您需要设置预配置/虚拟数据(在mongodb中使用特定数据),打开HTTP服务器,使用特定数据调用HTTP请求(使用特定查询进行发布/获取),以及检查HTTP响应正确的状态等。间谍需要检查/验证/验证是否以正确的参数调用服务并以正确的结果响应。此测试验证您是否已正确配置路由-控制器以针对特定HTTP请求的服务。
  2. 您必须有一个问题:如何测试负面情景?例如:404、500。然后,您需要知道哪个特定方案做什么,哪个结果为否定条件。例如:如果请求带有未知的ID查询,则响应将为404。或者如果express未连接到数据库,则响应将为500。您需要了解实际情况,然后再次提供require设置以产生否定响应。
  3. 对于问题:“当我运行一个测试时,一切正常。问题是当我针对不同的控制器运行多个单元测试时,存根在第二次运行中不起作用。”有几种可能的解决方案,主要要点是:必须确保正确准备了特定方案/案例的条件。

您可以做:

  • 创建sandbox,以确保在测试用例之间没有其他存根服务运行。
  • 在对每个服务进行测试运行之前,先启动新的http(和/或db)服务器,然后在运行后关闭服务器(例如:启动应用程序并使用真正的http客户端-替代supertest)
  • 以调试模式运行,以找出第二个存根为何未运行或未被调用或不起作用的原因,
  • 将实现从存根更改为间谍,您已经进行了单元测试,只需要检查服务是否被调用,然后检查总体响应即可。

希望这会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.