使用sinonjs测试在依赖项上调用new的函数

问题描述 投票:0回答:1

我非常困惑,希望得到一些帮助。

我认为这段代码的设计不是很糟糕,但是如果发现缺陷,请纠正我。

我似乎无法弄清楚如何测试依赖项上调用new的函数。这是我熬煮的课程。...去除了不相关的业务逻辑。

MyWrapper.js

const SomeLib = require('SomeLib');

module.exports.MyWrapper = class MyWrapper {
    constructor(username, password) {
        this._someLib = new SomeLib(username, password);
    }

    async getFoo(id) {
        // other business logic omitted
        // which was tested in the MyWrapper.spec.js
        return this._someLib.findById(id)
    }

    async saveFoo(object) {
        // other business logic omitted
        // which was tested in the MyWrapper.spec.js
        return this._someLib.save(object)
    }
}

MyApp.js

const MyWrapper = require('MyWrapper');

const process = async (message) => {
    const wrapper = new MyWrapper(process.env.username, process.env.password)
    // some business logic around the message...omitted
    const data = wrapper.getFoo(message.id);
    if(data) {
       // do stuff with the data
       wrapper.saveFoo(data);
    } else {
       console.log('no data found for message', message);
    }
}
module.exports = { process }

MyApp.spec.js

const sut = require('MyApp');

describe('MyApp', function(){
    describe('process', function(){
        it('should not call save when no data found', async function(){
             // how do I prevent 'new MyWrapper(process.env.username, process.env.password)' from being called???
             // how do I stub "wrapper.getFoo(message.id)" so I can return "undefined"
             const msg = {......};
             await sut.process(msg);
             // now assert wrapper.getFoo was called
             // now assert wrapper.saveFoo was *NOT* called
        });

        it('should call save when data is found', async function(){
             // how do I prevent 'new MyWrapper(process.env.username, process.env.password)' from being called???
             // how do I stub "wrapper.getFoo(message.id)" so I can return some JSON
             const msg = {......};
             await sut.process(msg);
             // now assert wrapper.getFoo was called
             // now assert wrapper.saveFoo was called
        });
    });
});
node.js unit-testing mocha sinon es6-class
1个回答
0
投票

通过以当前的结构形式查看代码,您将无法不调用new MyWrapper,因为该调用是在您正在调用的函数内部进行的。您可能想要做的是使用依赖注入来传递MyWrapper的实例。使用DI还可以使您传入Wrapper类的模拟版本,以更好地控制测试。看起来像这样:

// MyApp.js

const MyWrapper = require('MyWrapper');

const wrapper = new MyWrapper(process.env.username, process.env.password);

const process = async (message, wrapper) => {
    // some business logic around the message...omitted
    const data = wrapper.getFoo(message.id);
    if(data) {
       // do stuff with the data
       wrapper.saveFoo(data);
    } else {
       console.log('no data found for message', message);
    }
}
module.exports = { process }

您可能想在对您的应用程序有意义的其他地方实例化包装器,但是根据您提供的代码,现在可以在测试时传递您自己的Wrapper类的测试版本,如下所示:

// MyApp.spec.js

const sut = require('MyApp');

describe('MyApp', function(){
    describe('process', function(){
        it('should not call save when no data found', async function(){
             // how do I prevent 'new MyWrapper(process.env.username, process.env.password)' from being called???
             // how do I stub "wrapper.getFoo(message.id)" so I can return "undefined"
             const msg = {......};
             const wrapper = new MyWrapper();
             await sut.process(msg, wrapper);
             // now assert wrapper.getFoo was called
             // now assert wrapper.saveFoo was *NOT* called
        });

        ...
});

问题的第二部分涉及使用sinon创建类的存根。 sinon的文档here可能会为您提供如何制作存根并从存根类中返回您自己的值的最佳示例。

希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.