我如何testing我的asynchronous茉莉/ nodejs /诺言代码使用间谍

我有一个名为process-promise的模块(例子被简化了),它有一个单独的function,将一个Promise作为input并对其进行处理 – 它还使用外部模块调用其他function,如下所示:

//<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 spies按照以下代码对上述函数进行unit testing

 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已被调用['用户','名称'],但它从来没有被调用。 – 问题似乎是承诺是asynchronous的事实,但我已经包括完成function,因为其他SO问题已经build议,但这似乎并不能解决问题。 我的代码有什么问题? 大多数其他SO问题与angular度有关,所以不能帮助解决我的问题。

你在正确的轨道上,诺言是asynchronous的,然后在你的testingdonefunction被调用之前,诺言parsing为一个值。 done函数被用作callback来告诉testing引擎,所有的asynchronous代码已经完成。 在承诺解决了价值 (或者失败)之后应该被调用。

为了做到这一点,您需要对代码进行以下调整:

 //<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 }; 

testing将如下所示:

  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) 。 如果承诺解决了错误,这将确保您的testing失败。

可能的是,在你的testing代码执行的时候, 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'); }); }); 

另请注意, fakeUser实例中不存在setAll 。 我想你的意思是setDetails而不是setAll