2015-11-24 89 views
4

tl; dr是否可以在不重寫的情況下單元測試此代碼?我可以在沒有TestScheduler的情況下單元測試RxJS函數嗎?

http://jsbin.com/jezosegopo/edit?js,console

const keyUpObserver = ($input, fetchResults) => { 
    const source = Rx.Observable.fromEvent($input, 'keyup') 
     .map(e => e.target.value) 
     .filter(text => text.length > 2) 
     .debounce(300) 
     .distinctUntilChanged(); 

    return source.flatMapLatest(text => Rx.Observable.fromPromise(fetchResults(text))); 
}; 

在上面的代碼keyUpObserver在很大程度上基於所述RxJS自動完成示例,並且使用去抖動,以防止錘擊服務器。

我試圖單元測試這個功能,但興農的useFakeTimers似乎並不奏效。

const clock = sinon.useFakeTimers(); 

const $input = $('<input>'); 
const fetchResults = (text) => new Promise(resolve => resolve(text + ' done!')); 

keyUpObserver($input, fetchResults).subscribe(text => console.log(text)); 

$input.val('some text').trigger('keyup'); 

clock.tick(500); 

// Enough time should have elapsed to make this a new event 
$input.val('some more text').trigger('keyup'); 

我猜測這是不是興農相關要麼,不如說RxJS使用了一些必須由外部時鐘假不受影響內部時鐘。

鑑於這種情況,反正是有單元測試我keyUpObserver代碼,而無需重寫它也採取調度(默認在生產,測試單元測試)?


+0

是有一些原因,你不能拿調度? – paulpdaniels

回答

1

...接近答案:似乎RxJs使用默認/全球setTimeout實現其興農應該能夠覆蓋。至少這就是我通過閱讀defiultscheduler's code所說的內容,如果你沒有通過(如前所述)自定義調度程序的話。

不過,我對打算有點糊塗。從this little fork我希望只有第三個觸發器能夠實際觸發它所做的事情或者我應該脫節?

+1

你是正確的。雖然'setTimeout'是'DefaultScheduler'可以使用的選項之一,但在這種情況下,它將採用任何性能最高的選項。所以雖然很可能會使用'setTimeout',但不能保證它會保持這種狀態,並且這不會是一種依賴跨平臺或將來的行爲。 – paulpdaniels

+2

您好,非常感謝您的回覆。 tdeekens:我可能是錯的,但它好像它一旦文件被加載緩存的那些方法,所以當我試着踩滅了時鐘與興農它已經爲時已晚。至於意圖,如果你將最後一個clock.tick改爲400,那應該足以克服抖動併發送一個單獨的事件......但事實並非如此。 paulpdaniels:沒有_huge_原因,我無法通過調度程序,它只是感覺就像我不必人爲地重寫我的代碼,允許單元測試。 – larister

相關問題