使用proxyquire和mocha在单元测试中模拟方法调用时如何模拟时间延迟(超时)?

Posted

技术标签:

【中文标题】使用proxyquire和mocha在单元测试中模拟方法调用时如何模拟时间延迟(超时)?【英文标题】:How to simulate time delay (timeout) when mocking method calls in unit testing with proxyquire and mocha? 【发布时间】:2018-07-27 03:28:00 【问题描述】:

在测试模块 A 中的方法时,我使用 proxyquire 模拟模块 B 的方法(在模块 A 中使用 require() 注入)。模拟(模拟 admissionad.model.js 模块的 get_campaigns 方法):

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);
);

【问题讨论】:

【参考方案1】:
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 调用。

【讨论】:

沉了很多!你能检查我的更新吗?有没有办法在不创建新的承诺对象并解决它的情况下进行超时,因为它会强烈地乱扔代码? 没问题,搞定了) @AntonPegov 好的

以上是关于使用proxyquire和mocha在单元测试中模拟方法调用时如何模拟时间延迟(超时)?的主要内容,如果未能解决你的问题,请参考以下文章

proxyquire 错误:ENOENT:没有这样的文件或目录,scandir

使用 Mocha 和 Node.js 对私有函数进行单元测试

mocha+Typescript的单元测试搭建

使用mocha编写node服务单元测试

Mocha 单元测试框架简介

mocha 单元测试中的 Highchart 导入错误