2017-11-18 274 views
1

我正在使用Nodejs,RxJS和Typescript開發應用程序。使用chai和mocha在nodejs中觀察結果的簡單測試

應用程序有它返回一個可觀察的字符串

myObsFunction() : Observable<string> { 
... do stuff 
} 

我希望能夠做一個簡單的測試來檢查,當我訂閱了這個功能我得到預期的字符串的函數。我使用摩卡,所以我寫了下面的測試情況

import { expect } from 'chai'; 
import 'mocha'; 

import {myObsFunction} from './my-source-file'; 

describe('myObsFunction function',() => { 

    it('check myObsFunction',() => { 
     const expectedString = 'abc'; 
     let receivedString: string; 
     myObsFunction().subscribe(
      data => receivedString = data, 
      error => console.error(error), 
      () => expect(receivedString).to.equal(expectedString) 
     ) 
    }); 

}); 

不幸被我預期這個測試用例不起作用。它始終表現爲即使在出現錯誤的情況下也能成功通過。 expect檢查我已經寫在onCompleted函數不會發出任何信號,即使expectedString不等於receivedString。實際執行的onCompleted功能(我可以看到這個剛剛加入的onCompleted功能console.log指令),但預計不會發出信號時出現錯誤

有沒有什麼辦法,而無需啓動運行這樣簡單的測試任何錯誤使用調度程序和更復雜的機制?

+1

看來'myObsFunction'異步運行,所以你需要使用''的回調it'到done'信號其執行結束。 –

回答

1

測試邏輯看起來很合理,這裏是摩卡和柴的一個工作示例。

console.clear() 
 
const Observable = Rx.Observable 
 
mocha.setup('bdd'); 
 
const assert = chai.assert; 
 
const should = chai.should(); 
 
const expect = chai.expect; 
 
const done = mocha.done; 
 

 

 
const myObsFunction =() => Observable.of('xyz'); 
 
const myAsyncObsFunction =() => Observable.timer(500).mapTo('xyz'); 
 

 
describe('RxJs Observable Test Examples', function() { 
 

 
    it('should test the observable succeeds', function() { 
 
    const expectedString = 'xyz'; 
 
    let receivedString: string; 
 
    myObsFunction().subscribe(
 
     data => receivedString = data, 
 
     error => console.error(error), 
 
    () => { 
 
     expect(receivedString).to.equal(expectedString); 
 
     } 
 
    ) 
 
    }); 
 

 
    it('should test the observable fails', function() { 
 
    const expectedString = 'abc'; 
 
    let receivedString: string; 
 
    myObsFunction().subscribe(
 
     data => receivedString = data, 
 
     error => console.error(error), 
 
    () => { 
 
     expect(receivedString).to.equal(expectedString); 
 
     } 
 
    ) 
 
    }); 
 

 
    it('should test the async observable succeeds', function (done) { 
 
    const expectedString = 'xyz'; 
 
    let receivedString: string; 
 
    myAsyncObsFunction().subscribe(
 
     data => receivedString = data, 
 
     error => console.error(error), 
 
    () => { 
 
     //expect(receivedString).to.equal(expectedString); 
 
     if (receivedString !== expectedString) { 
 
      return done(new Error("Failed match")); 
 
     } else { 
 
      return done(); 
 
     } 
 
     } 
 
    ) 
 
    }); 
 

 
    it('should test the async observable fails', function (done) { 
 
    const expectedString = 'abc'; 
 
    let receivedString: string; 
 
    myAsyncObsFunction().subscribe(
 
     data => receivedString = data, 
 
     error => console.error(error), 
 
    () => { 
 
     //expect(receivedString).to.equal(expectedString); 
 
     if (receivedString !== expectedString) { 
 
      return done(new Error("Failed match")); 
 
     } else { 
 
      return done(); 
 
     } 
 
     } 
 
    ) 
 
    }); 
 
}); 
 

 
mocha.run();
<link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.min.css" rel="stylesheet"/> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script> 
 
<div id="mocha"></div>


誤報當觀察到的永遠不會觸發

有一件事我遇到了誤報,如果觀察到永遠不會觸發。這是我用來解決這個問題的一些輔助函數。請注意,take(1)可確保已完成的事件被觸發,即使observable本身沒有完成。

console.clear() 
 
const Observable = Rx.Observable 
 
mocha.setup('bdd'); 
 
const assert = chai.assert; 
 
const should = chai.should(); 
 
const expect = chai.expect; 
 

 
const subscribeAndTestValue = function (observable: Observable<any>, expected: any): string { 
 
    let fail = ''; 
 
    let wasSubscribed = false; 
 
    const sub = observable 
 
    .take(1) 
 
    .subscribe(
 
     (result) => { 
 
     if (result !== expected) { 
 
      fail = 'Subscription result does not match expected value'; 
 
     } 
 
     wasSubscribed = true; 
 
     }, 
 
     (error) => { 
 
     fail = 'Subscription raised an error'; 
 
     }, 
 
     (/*completed*/) => { 
 
     // When testing a single value, 
 
     // need to check that the subscription was activated, 
 
     // otherwise the expected value is never tested 
 
     if (!wasSubscribed) { 
 
      fail = 'Subscription produced no results'; 
 
     } 
 
     } 
 
    ); 
 
    sub.unsubscribe(); 
 
    return fail; 
 
} 
 

 
const subscribeAndTestNoDataEmitted = function (observable: Observable<any>): string { 
 
    let fail; 
 
    let wasSubscribed = false; 
 
    const sub = observable 
 
    .subscribe(
 
     (result) => { 
 
     wasSubscribed = true; 
 
     }, 
 
     (error) => { 
 
     fail = 'Subscription raised an error'; 
 
     }, 
 
     (/*completed*/) => { 
 
     if (wasSubscribed) { 
 
      fail = 'Subscription produced values when none were expected'; 
 
     } 
 
     } 
 
    ); 
 
    sub.unsubscribe(); 
 
    return fail; 
 
} 
 

 
const emptyObservable = Observable.empty(); 
 
const nonCompletingObservable = Observable.interval(1000); 
 
const emittingObservable = Observable.of('abc'); 
 

 
describe('RxJs Observable Test Examples', function() { 
 

 
    it('should test the observable fires', function() { 
 
    const expectedString = 'xyz'; 
 
    const failed = subscribeAndTestValue(emptyObservable, expectedString); 
 
    expect(failed).to.equal('Subscription produced no results'); 
 
    }); 
 

 
    it('should test first observable value of a non-completing observable', function() { 
 
    const expectedString = '0'; 
 
    const failed = subscribeAndTestValue(nonCompletingObservable, expectedString); 
 
    expect(failed).to.equal(''); 
 
    }); 
 

 
    it('should test the observable does not fire', function() { 
 
    const expectedString = 'xyz'; 
 
    const failed = subscribeAndTestNoDataEmitted(emittingObservable, expectedString); 
 
    expect(failed).to.equal('Subscription produced values when none were expected'); 
 
    }); 
 
    
 
}); 
 

 
mocha.run();
<link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.min.css" rel="stylesheet"/> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.min.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script> 
 
<div id="mocha"></div>

+0

謝謝,答案是正確的,並幫助我繼續前進。對於那些使用Typescript和當前最新版本的Mocha(4.0.1)的用戶來說,只有一條評論。在這種情況下,您可以通過'import'mocha';'導入Mocha,然後使用'done' – Picci

相關問題