Stub一个独立的模块.使用rewire导出函数



我正在尝试stubmodule.exports函数。但我遇到了一些麻烦。我会给你一个sudo代码的情况。

MyController.js

const sendOTPOnPhone = rewire('../../src/services/OtpService/sendOTPOnPhone')
module.exports = async function(req, res) {
const { error, data } = await sendOTPOnPhone(req.query.phone) //this is I want to stub
if(error)
return return res.send(error)
return res.send(data)
}

sendOTPService.js

module.exports = async function(phone) {
const result = await fetch(`external-api-call`)
if(result.status !== 'success')
return {
error: "Failed to send OTP!",
data: null
}
return {
error: null,
data: result
}
}

sendOTPTest.js

const expect = require('chai').expect
const request = require('supertest')
const sinon = require('sinon')
const rewire = require('rewire')
const sendOTPOnPhone = rewire('../../src/services/OtpService/sendOTPOnPhone')
const app = require('../../src/app')
describe('GET /api/v1/auth/otp/generate', function () {
it('should generate OTP', async () => {
let stub = sinon.stub().returns({
error: null,
data: "OTP sent"
})
sendOTPOnPhone.__set__('sendOTPOnPhone', stub)
const result = await request(app)
.get('/api/v1/auth/otp/generate?phone=8576863491')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
expect(stub.calledOnce).to.be.true
console.log(result.body)
// expect(result).to.equal('promise resolved'); 
})
})

上面的测试失败了,并没有调用存根。我不知道我错过了什么?如果我在sendOTPService:中这样做

const sendOTP = async function() {}
module.exports = {
sendOTP
}

并且这在控制器中。

const { error, data } = sendOTPOnPhone.sendOTPOnPhone(req.query.phone)

它有效

但我像const {sendOTPOnPhone } = require('../sendOTPService')一样导入它,它不起作用

我知道破坏会更改对象的引用
有人能提出解决办法吗
使用rewire是否可以实现这一点?或者可以用proxyquire来完成
请有人提出建议好吗

这是使用proxyquire的集成测试解决方案,您应该使用Globally override require。

app.js:

const express = require('express');
const controller = require('./controller');
const app = express();
app.get('/api/v1/auth/otp/generate', controller);
module.exports = app;

controller.js:

let sendOTPOnPhone = require('./sendOTPOnPhone');
module.exports = async function(req, res) {
const { error, data } = await sendOTPOnPhone(req.query.phone);
if (error) return res.send(error);
return res.send(data);
};

sendOTPOnPhone.js:

module.exports = async function(phone) {
const result = await fetch(`external-api-call`);
if (result.status !== 'success')
return {
error: 'Failed to send OTP!',
data: null,
};
return {
error: null,
data: result,
};
};

sendOTP.test.js:

const request = require('supertest');
const sinon = require('sinon');
const proxyquire = require('proxyquire');
describe('GET /api/v1/auth/otp/generate', function() {
it('should generate OTP', async () => {
let stub = sinon.stub().resolves({
error: null,
data: { message: 'OTP sent' },
});
stub['@global'] = true;
const app = proxyquire('./app', {
'./sendOTPOnPhone': stub,
});
const result = await request(app)
.get('/api/v1/auth/otp/generate?phone=8576863491')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200);
sinon.assert.calledOnce(stub);
console.log(result.body);
});
});

集成测试结果与覆盖率报告:

GET /api/v1/auth/otp/generate
{ message: 'OTP sent' }
✓ should generate OTP (2373ms)

1 passing (2s)
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   68.75 |       25 |      50 |   73.33 |                   
app.js            |     100 |      100 |     100 |     100 |                   
controller.js     |   83.33 |       50 |     100 |     100 | 5                 
sendOTPOnPhone.js |      20 |        0 |       0 |      20 | 2-4,8             
-------------------|---------|----------|---------|---------|-------------------

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

我已经回答了一个类似的问题这里是存根SMS otp方法(不使用像proxyquire这样的外部依赖性(

基本上,问题出在出口上。将sendOtp方法移动到通用位置,例如用户模型或模式。导入模型,截断其函数。它应该可以正常工作。

您正在存根导入的名为sendOtp的属性,而不是原始函数。

最新更新