【问题标题】:how do i test my async jasmine/nodejs/promise code using Spies我如何使用 Spies 测试我的异步 jasmine/nodejs/promise 代码
【发布时间】:2017-02-22 21:38:22
【问题描述】:

我有一个名为 process-promise 的模块(示例已简化),它有一个函数,该函数将 Promise 作为输入并对其进行处理 - 它还使用其外部的模块调用其他函数,如下所示:

//<process-promise.js>
let User = require('user-module'); 

let processPromise = (promiseObj) => {
        let user = new User();

        promiseObj.then((full_name) => {
            const [ fname, sname ] = full_name.split(' ');

            if (fname && sname) {
                user.setDetails(fname, sname);
            } else{
               console.log('nothing happened');
            }

        }).catch((err) => {
            console.log(err.message);
        });
    };

module.exports = {
processPromise
};

我正在尝试按照以下代码使用 Jasmine、Rewire 和 Jasmine 间谍对上述功能进行单元测试

let rewire = require('rewire');
let mod = rewire('process-promise');

describe('process-promise module', () => {

beforeEach(() => {

    this.fakeUser = createSpyObj('fake-user', ['setDetails']);
    this.fakeUserMod = jasmine.createSpy('fake-user-mod');
    this.fakeUserMod.and.returnValue(this.fakeUser)

    this.revert = mod.__set__({
        User: this.fakeUserMod
    });

});

    afterEach(() => {
        this.revert();
    });


    it('fakeUser.setDetails should be called', (done) => {
        mod.processPromise(Promise.resolve('user name'));
        done();
        expect(this.fakeUser.setDetails).toHaveBeenCalledWith('user','name');
    });

});

我希望间谍 this.fakeUser.setDetails 应该被调用,但我从 Jasmine 收到消息“预期间谍 fake-user.setAll 已使用 ['user','name'] 调用,但从未调用。” - 问题似乎是承诺是异步的,但我已经包含了 done 功能,正如其他 SO 问题所建议的那样,但这似乎并不能解决我的问题。我的代码有什么问题?大多数其他 SO 问题都与角度有关,所以对我的问题没有帮助。

【问题讨论】:

    标签: javascript node.js asynchronous jasmine


    【解决方案1】:

    您走在正确的轨道上,promise 是异步的,然后在您的测试中调用 done 函数,然后再将 promise 解析为一个值。 done 函数用作回调来告诉测试引擎,您的所有异步代码都已完成。它应该在promise解析为一个值(或者失败)之后调用。

    为此,您需要对代码进行以下调整:

    //<process-promise.js>
    let User = require('user-module'); 
    
    let processPromise = (promiseObj) => {
            let user = new User();
    
            // return a promise, to allow a client to chain a .then call
            return promiseObj.then((full_name) => {
                const [ fname, sname ] = full_name.split(' ');
    
                if (fname && sname) {
                    user.setDetails(fname, sname);
                } else{
                   console.log('nothing happened');
                }
    
            }).catch((err) => {
                console.log(err.message);
            });
        };
    
    module.exports = {
        processPromise
    };
    

    测试将如下所示:

        it('fakeUser.setAll should be called', (done) => {
            mod.processPromise(Promise.resolve('user name')).then(() => {
                expect(this.fakeUser.setAll).toHaveBeenCalledWith('user','name');
                done();
            }).catch(done);
        });
    

    请务必添加.catch(done)。这将确保您的测试失败,以防 Promise 解析为错误。

    【讨论】:

    • 非常感谢您快速而有帮助的回复。您建议的更改效果很好,这解决了我的测试问题。
    【解决方案2】:

    很可能,当您的测试代码执行时,promise 尚未传播到被测代码。简单地调用done() 并没有同步魔法。

    我不熟悉rewire,所以我将分享一个使用示例 proxyquire

    const proxyquire = require('proxyquire');
    
    describe('process-promise module', () => {
        const fakeUser = { setDetails: jasmine.createSpy('setDetails') };
        const fakeUserMod = jasmine.createSpy('fake-user-mod').and.returnValue(fakeUser);
        const promiseObj = Promise.resolve('user name');
    
        beforeEach((done) => {
            const processPromiseMod = proxyquire('process-promise', {
                'user-module': fakeUserMod,
            });
    
            processPromiseMod.processPromise(promiseObj);
    
            promiseObj.then(() => done());
        });
    
    
        it('fakeUser.setDetails should be called', () => {
            expect(fakeUser.setDetails).toHaveBeenCalledWith('user','name');
        });
    });
    

    还要注意setAll 不存在于fakeUser 实例中。我猜你的意思是setDetails 而不是setAll

    【讨论】:

    • 您好,非常感谢您的建议!如果我没有通过 rewire 解决它,我肯定会调查您在此处建议的 proxyquire 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多