如何使用间谍

时间:2017-02-22 21:38:22

标签: javascript node.js asynchronous jasmine

我有一个名为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');
    });

});

我希望Spy this.fakeUser.setDetails应该被调用,但是我从Jasmine那里得到消息“预期spy fake-user.setAll用['user','name'调用]但它从未被调用过“。 - 问题似乎是承诺是异步的事实,但我已经包括完成功能,因为其他SO问题已经建议,但这似乎并没有解决我的问题。我的代码有什么问题?大多数其他SO问题与角度有关,所以对我的问题没有帮助。

2 个答案:

答案 0 :(得分:1)

您走在正确的轨道上,承诺是异步的,然后在承诺解析为值之前调用您的测试中的done函数。 //<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)

请务必添加RecyclerView。这将确保您的测试失败,以防承诺解决错误。

答案 1 :(得分:0)

在您的测试代码执行时,很可能承诺未传播到测试中的代码。简单地调用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