首页 > 解决方案 > Sinon 存根无法使用 module.exports = { f1, f2}

问题描述

我有这个发送 otp 的文件,如下所示。

OtpService.js

const generateOTP = async function() {
 //
}

const verifyOTP = async function() {
//
}

module.exports = {
 generateOTP,
 verifyOTP
}

下面是使用这些方法的控制器otp.js

const { verifyOTP, generateOTP } = require('../../services/OtpService')

const verify = async function(req, res) {
 const {error, data} = await generateOTP(req.query.phone)
}

const send = async function(req, res) {
 const {error, data} = await verifyOTP(req.query.phone, req.query.otp)
}

module.exports = {
 send,
 verify
}

下面是测试文件 otp.test.js

const sinon = require('sinon');
const expect = require('chai').expect
const request = require('supertest')
const OtpService = require('../../src/services/OtpService')
console.log(OtpService)
describe('GET /api/v1/auth/otp', function() {
  let server 
  let stub
  const app = require('../../src/app')
  stub = sinon.stub(OtpService, 'generateOTP').resolves({
    error: null,
    data: "OTP Sent"
  })
  server = request(app)
  it('should generate OTP', async () => {
    const result = await server
        .get('/api/v1/auth/otp/send?phone=7845897889')
        .set('Accept', 'application/json')
        .expect('Content-Type', /json/)
        .expect(200)
        console.log(result.body)
    expect(stub.called).to.be.true
    expect(result).to.be.a('Object')
  });
});

上面不起作用,在控制器中调用时它没有存根generateOTPand方法。verifyOTP

但是,如果我调用OtpService.generateOTP()otp.test.js那么它在那里工作,但它在控制器中不起作用。

诗乃如何在这里工作?

我在这里很困惑。要求应用程序然后存根是正确的还是先存根然后要求是正确的?

我已经尝试了两种方法,尽管它们都不起作用。我也尝试使用before() and beforeEach().

下面是我的文件夹结构。

在此处输入图像描述

otp.js(控制器)在这里controller->AuthController->otp.js

otp.test.js在这儿test->auth->otp.test.js

OtpService.js就在里面services

更新

我发现了问题所在。如果我不在控制器中使用破坏功能,一切正常。所以,使用OtpService.generateOTP作品。

问题在于对象的破坏。

const { verifyOTP, generateOTP } = require('../../services/OtpService')

上面是在存根之前运行的。所以verifyOTP并且generateOTP已经参考了这些unstubbed方法。

我需要一个解决方法。我想使用破坏功能。

标签: javascriptnode.jsintegration-testingsinonsupertest

解决方案


我使用proxyquire包来存根OtpService模块。下面的示例是单元测试,但您可以使用这种方式进行集成测试。

例如

otp.js

const { verifyOTP, generateOTP } = require('./OtpService');

const verify = async function(req, res) {
  return generateOTP(req.query.phone);
};

const send = async function(req, res) {
  return verifyOTP(req.query.phone, req.query.otp);
};

module.exports = {
  send,
  verify,
};

OtpService.js

const generateOTP = async function() {
  //
};

const verifyOTP = async function() {
  //
};

module.exports = {
  generateOTP,
  verifyOTP,
};

otp.test.js

const proxyquire = require('proxyquire');
const sinon = require('sinon');

describe('60704684', () => {
  it('should send', async () => {
    const otpServiceStub = {
      verifyOTP: sinon.stub().resolves({ error: null, data: 'fake data' }),
      generateOTP: sinon.stub(),
    };
    const { send } = proxyquire('./otp', {
      './OtpService': otpServiceStub,
    });
    const mReq = { query: { phone: '123', otp: 'otp' } };
    const mRes = {};
    await send(mReq, mRes);
    sinon.assert.calledWithExactly(otpServiceStub.verifyOTP, '123', 'otp');
  });

  it('should verfiy', async () => {
    const otpServiceStub = {
      verifyOTP: sinon.stub(),
      generateOTP: sinon.stub().resolves({ error: null, data: 'fake data' }),
    };
    const { verify } = proxyquire('./otp', {
      './OtpService': otpServiceStub,
    });
    const mReq = { query: { phone: '123' } };
    const mRes = {};
    await verify(mReq, mRes);
    sinon.assert.calledWithExactly(otpServiceStub.generateOTP, '123');
  });
});

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

  60704684
    ✓ should send (1744ms)
    ✓ should verfiy


  2 passing (2s)

---------------|---------|----------|---------|---------|-------------------
File           | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
---------------|---------|----------|---------|---------|-------------------
All files      |     100 |      100 |      50 |     100 |                   
 OtpService.js |     100 |      100 |       0 |     100 |                   
 otp.js        |     100 |      100 |     100 |     100 |                   
---------------|---------|----------|---------|---------|-------------------

源代码:https ://github.com/mrdulin/expressjs-research/tree/master/src/stackoverflow/60704684


推荐阅读