【问题标题】:How to mock return value of async function?如何模拟异步函数的返回值?
【发布时间】:2019-06-15 20:25:53
【问题描述】:

我正在尝试测试使用“easy-soap-request”库的函数。 我想模拟“soapRequest”函数返回的结果。

我尝试了this,但没有成功,我不断从外部 API 获取数据。

client.js

const soapRequest = require('easy-soap-request');

async function get_data(){
    var response = await soapRequest(url, auth_headers) //this is what I want to mock
    var result;
    result = some_parsing_function(response); //this is what I want test
    return result;
}

test.js

const client = require('../../client');

describe('get_data tests', () =>{
    it('should test sth', function (done) {

        var stubed = stub(client, 'soapRequest').returns('dummy value');

        client.get_data().then((result) => {
            //assertions
            console.log(result) //result still has value from external service
            done();
        });

    })
});

编辑:

所以我尝试按照其中一个答案的建议使用 sinon.fake()。

const client = require('../../client');

describe('get_data tests', () =>{
    it('should test sth', function (done) {

        var fake_soap = fake(async () => {
            return 12345;
        });

        replace(cilent, 'soapRequest', fake_soap);

        client.soapRequest().then((res) => {
            console.log(res); // 12345
        })

        client.get_data().then((result) => {
            //assertions
            console.log(result) //still original value from external service
            done();
        });

    })
});

【问题讨论】:

  • 使用mock-module等来模拟一个模块。这是诗浓一个人做不到的。

标签: javascript node.js unit-testing ecmascript-6 sinon


【解决方案1】:

在源文件中,soapRequest 变量本身是一个函数不是命名导入(对象),因此不可能仅依赖sinon.stub

如果看一下easy-soap-request源代码,很明显,它导出了一个函数https://github.com/circa10a/easy-soap-request/blob/master/index.js#L14

根据我的经验,对于这种情况,可以通过添加proxyquire 来解决,如下所示。

const proxyquire = require('proxyquire');
const sinon = require('sinon');

// we mock `easy-soap-request` (the library name) by using `sinon.stub`
const client = proxyquire('../../client', { 'easy-soap-request': sinon.stub().returns('dummy value') })

describe('get_data tests', () =>{
    it('should test sth', async () => { // use async/await for better code
        const result = await client.get_data();
        console.log(result); // dummy value
    })
});

如果你不想使用sinon,你也可以这样做

const client = proxyquire('../../client', { 'easy-soap-request': () => 'dummy value' })

参考:

https://www.npmjs.com/package/proxyquire

希望对你有帮助

【讨论】:

    【解决方案2】:

    这样就可以了:

    let asyncHandler = sinon.fake(async () => {});
    

    Documentation

    更新:

    我的错!我没有很好地理解这个问题。这是解决它的一种方法。此外,最好将外部依赖项与应用程序逻辑分开。所以,我添加了一个新文件来发出肥皂请求。然后,为测试请求存根就变得容易了。

    soap-connector.js

    const soapRequest = require('easy-soap-request');
    exports.request = async function request(url, auth_headers) {
      return soapRequest(url, auth_headers);
    };
    

    client.js

    const soapConnector = require('./soap-connector');
    async function get_data(){
        var response = await soapConnector.request(url, auth_headers) //this is what I want to mock
        var result;
        result = some_parsing_function(response); //this is what I want test
        return result;
    }
    

    test.js

    const soapConnector = require('../../soap-connector');
    const client = require('../../client');
    
    describe('get_data tests', () =>{
        it('should test sth', function (done) {
    
            var stubed = stub(soapConnector, 'request').callsFake(async () => {
                return 12345;
            });
    
            client.get_data().then((result) => {
                //assertions
                console.log(result) //result still has value from external service
                done();
            });
    
        })
    });
    

    Documentation

    【讨论】:

      猜你喜欢
      • 2020-07-29
      • 1970-01-01
      • 2018-01-03
      • 2021-03-04
      • 1970-01-01
      • 2022-01-14
      • 2020-04-06
      • 2017-12-16
      相关资源
      最近更新 更多