使用proxyquire和mocha在单元测试中模拟方法调用时如何模拟时间延迟(超时)?
How to simulate time delay (timeout) when mocking method calls in unit testing with proxyquire and mocha?
在测试模块A中的方法时,我正在模拟模块B的方法(在模块A中注入require())。模拟(模拟get_campaigns方法admitad.model.js模块):
const admitadModelMock = {
'../services/admitad.model': {
get_campaigns: (limit, page) => new Promise((resolve, reject) =>
setTimeout(resolve({campaigns: testData, count: 1000}), 5000)
),
},
};
测试:
it('shold get all campaigns from Admitad', async function () {
this.timeout(60000);
let err, data;
// mock dependencie (get_campaigns() of module B will be mocked):
let $serviceStubbed = proxyquire('../services/campaign-sync', admitadModelMock);
// getAdmitadCampaigns() just calls get_campaigns method of module B
[err, data] = await to($serviceStubbed.getAdmitadCampaigns(50));
data.length.should.be.equal(50);
});
问题是测试通过时没有预期的 5 秒延迟。
更新。
这是有效的:
setTimeout(() => resolve({campaigns: mockedCampaigns, count: 1000}), 2000)
这是我最后的好方法:
// helper to wrap timeout generation
const timer = (data, time) =>
new Promise((resolve, reject) =>
setTimeout(() => resolve(data), time)
);
// Factory function to generate mock with data we need
const blacklistedModelMockFactory =
(onRead = [], onUpdate = 'Ok', onCreate = 'Ok', onDelete = 'Ok') => ({
'../services/campaigns-blacklist.model': {
read: () => timer(onRead, 2000),
update: () => timer(onUpdate, 2000),
create: () => timer(onCreate, 1000),
delete: () => timer(onDelete, 1000),
},
});
// Test example
it('should filter Registered and Blacklisted collections', async function () {
this.timeout(60000);
$service.should.have.property('filterRB').a('function');
const sourceRegistered = mockedCampaigns.slice(5, 10);
const sourceBlacklisted = mockedCampaigns.slice(15, 18);
let error, success;
// mock dependencies in tested module with our expected data:
let $serviceStubbed = proxyquire(
'../services/campaign-sync', Object.assign(
{},
blacklistedModelMockFactory(sourceBlacklisted),
registeredModelMockFactory(sourceRegistered)
)
);
[error, success] = await to($serviceStubbed.filterRB(mockedCampaigns));
expect(error).to.be.equal(null);
success.filtered.length.should.be.equal(12);
success.blacklisted.length.should.be.equal(3);
success.registered.length.should.be.equal(5);
});
setTimeout(resolve({campaigns: testData, count: 1000}), 5000)
上面的线路调用流程可以解释如下。
let res = resolve({campaigns: testData, count: 1000});
setTimeout(res, 5000);
你不想要那个,是吗:-)
试试,
setTimeout(() => resolve({ campaigns: testData, count: 1000 }), 5000)
因为它将 resolve
调用包装在一个匿名函数中,并将其作为第一个参数传递给 setTimeout
调用。
在测试模块A中的方法时,我正在模拟模块B的方法(在模块A中注入require())。模拟(模拟get_campaigns方法admitad.model.js模块):
const admitadModelMock = {
'../services/admitad.model': {
get_campaigns: (limit, page) => new Promise((resolve, reject) =>
setTimeout(resolve({campaigns: testData, count: 1000}), 5000)
),
},
};
测试:
it('shold get all campaigns from Admitad', async function () {
this.timeout(60000);
let err, data;
// mock dependencie (get_campaigns() of module B will be mocked):
let $serviceStubbed = proxyquire('../services/campaign-sync', admitadModelMock);
// getAdmitadCampaigns() just calls get_campaigns method of module B
[err, data] = await to($serviceStubbed.getAdmitadCampaigns(50));
data.length.should.be.equal(50);
});
问题是测试通过时没有预期的 5 秒延迟。
更新。
这是有效的:
setTimeout(() => resolve({campaigns: mockedCampaigns, count: 1000}), 2000)
这是我最后的好方法:
// helper to wrap timeout generation
const timer = (data, time) =>
new Promise((resolve, reject) =>
setTimeout(() => resolve(data), time)
);
// Factory function to generate mock with data we need
const blacklistedModelMockFactory =
(onRead = [], onUpdate = 'Ok', onCreate = 'Ok', onDelete = 'Ok') => ({
'../services/campaigns-blacklist.model': {
read: () => timer(onRead, 2000),
update: () => timer(onUpdate, 2000),
create: () => timer(onCreate, 1000),
delete: () => timer(onDelete, 1000),
},
});
// Test example
it('should filter Registered and Blacklisted collections', async function () {
this.timeout(60000);
$service.should.have.property('filterRB').a('function');
const sourceRegistered = mockedCampaigns.slice(5, 10);
const sourceBlacklisted = mockedCampaigns.slice(15, 18);
let error, success;
// mock dependencies in tested module with our expected data:
let $serviceStubbed = proxyquire(
'../services/campaign-sync', Object.assign(
{},
blacklistedModelMockFactory(sourceBlacklisted),
registeredModelMockFactory(sourceRegistered)
)
);
[error, success] = await to($serviceStubbed.filterRB(mockedCampaigns));
expect(error).to.be.equal(null);
success.filtered.length.should.be.equal(12);
success.blacklisted.length.should.be.equal(3);
success.registered.length.should.be.equal(5);
});
setTimeout(resolve({campaigns: testData, count: 1000}), 5000)
上面的线路调用流程可以解释如下。
let res = resolve({campaigns: testData, count: 1000});
setTimeout(res, 5000);
你不想要那个,是吗:-)
试试,
setTimeout(() => resolve({ campaigns: testData, count: 1000 }), 5000)
因为它将 resolve
调用包装在一个匿名函数中,并将其作为第一个参数传递给 setTimeout
调用。