2017-02-22 32 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

相關問題