我正在尝试stub
和module.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的属性,而不是原始函数。