2017-02-22 33 views
2

我有一个称为process-promise的模块(示例已被简化),它具有将Promise作为输入并处理它的单个函数 - 它还调用其他使用模块外面如下功能:我如何使用Spies测试我的异步jasmine/nodejs/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 
}; 

我试图单元测试使用茉莉,重新布线和茉莉间谍上述函数按照以下代码

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应该被调用,但我从茉莉花“预期的间谍fake-user.setAll已被['user','name']调用,但从未被调用过。“ - 问题似乎是承诺是异步的事实,但我已经包含完成功能,因为其他SO问题已经提出,但这似乎并没有解决我的问题。我的代码有什么问题?大多数其他SO问题与角度有关,所以不能帮助解决我的问题。

回答

1

你是在正确的轨道上,承诺是异步的,然后done函数在你的测试被调用之前被调用的promise被解析为一个值。使用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) 。如果承诺解决了错误,这将确保您的测试失败。

+0

非常感谢您的快速和有益的回应。您建议的更改工作得很好,这已解决了我的测试问题。 – Dev

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

+0

嗨,非常感谢您的建议!如果我没有用rewire解决它,我肯定会调查你在这里建议的proxyquire方法。 – Dev

相关问题