[英]How do I stub a method in an object that is loaded in my class/method under test?
Our MEANJS
application has a class (Eg, CompanyService
) that loads an object (Eg, CompanyRepo
) of another class and calls a method on it. 我们的
MEANJS
应用程序具有一个类(Eg, CompanyService
),该类加载另一个类的对象(Eg, CompanyRepo
)并在其上调用一个方法。 I am trying to write unit tests for the CompanyService
class and would need to stub a method in the CompanyRepo
method to simulate a promise rejection. 我正在尝试为
CompanyService
类编写单元测试,并且需要在CompanyRepo
方法中存根方法以模拟承诺拒绝。 However, despite the stub, the CompanyService
method call seems to call the actual CompanyRepo
method call. 但是,尽管有存根,但
CompanyService
方法调用似乎调用了实际的CompanyRepo
方法调用。
The code flow is as below, 代码流如下所示,
companyService method companyService方法
function isDomainExists(domain) {
return new Promise(function(resolve, reject) {
companyRepo.getCompanyByDomain(domain)
.then(function (company) {
return resolve(company);
}, function(rejected) {
return reject("Error");
})
} });
Unit test method 单元测试方法
var stub = sinon.stub(companyRepo,"getCompanyByDomain").rejects("error"); it('Should return company not registered if there is a DB error', function() {
return companyService.isDomainExists("test company").should.eventually.be.rejected(); }); stub.restore();
Output 输出量
Company service isDomainExists method Should return company not registered if there is a DB error: AssertionError: expected promise to be rejected but it was fulfilled with { Object ($__, isNew, ...) }
公司服务isDomainExists方法如果出现数据库错误,应返回未注册的公司:AssertionError:期望的诺言将被拒绝,但已通过{Object($ __,isNew,...)}实现。
I think I can understand what is happening here. 我想我可以理解这里发生的事情。 The companyService class has a require statement that loads the companyRepo class which gets executed even before the stubbing happens.
companyService类具有一个require语句,该语句将加载companyRepo类,该类甚至在存根发生之前就已执行。 Is there any method by which I can avoid this from happening?
有什么方法可以避免这种情况的发生? What is the recommended best practice in this case?
在这种情况下,建议的最佳做法是什么?
I couldn't get it to work properly with should, but did get this to work, see if it helps: 我无法使其正常使用,但确实可以正常工作,请查看是否有帮助:
companyService: companyService:
var companyRepo = require('./companyRepo');
function isDomainExists(domain) {
return new Promise(function (resolve, reject) {
companyRepo.getCompanyByDomain(domain)
.then(function (company) {
console.log('----in main resolve')
return resolve(company);
}, function (rejected) {
console.log('----in error catch')
// return reject(new Error('Errorx'));
return reject('Error');
});
});
};
exports.isDomainExists = isDomainExists;
companyRepo 公司回购
exports.getCompanyByDomain = () => {
console.log('-----in real getCompanyByDomain');
return Promise.resolve('resolve from real function');
}
Test 测试
it('Should return company not registered if there is a DB error', async function () {
var stub = sinon.stub(companyRepo, "getCompanyByDomain").rejects("fake_error");
await expect(companyService.isDomainExists("test company")).to.eventually.be.rejectedWith('Error');
stub.restore();
});
It is rejecting with Error (and not fake_error) because your reject function sends 'Error' regardless. 它拒绝并带有错误(而不是fake_error),因为无论如何,拒绝函数都会发送“错误”。
Should sometimes acts funny, no idea why, also, try moving stub / resotre inside the test (or in beforeEach, afterEach). 有时应该表现得很滑稽,不知道为什么,还尝试在测试内部(或在beforeEach,afterEach中)移动存根/返回。
There was also a small typo in companyRepo definition. companyRepo定义中也有一个小的错字。
If nothing else works (i've seen this in some cases), try rewire to stub instead: 如果没有其他效果(在某些情况下我已经看到了),请尝试将其重新连接到存根:
var rewire = require('rewire')
//notice not using require here
var companyService = rewire('./companyService');
it('should stub', async () => {
let fake = {
getCompanyByDomain: () => {
console.log('------rewired stub')
return Promise.reject('rewired_error');
}
}
companyService.__set__('companyRepo', fake);
await expect(companyService.isDomainExists("test company")).to.eventually.be.rejectedWith('Error');
//reset
companyService = rewire('./companyService');
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.