2015-02-24 43 views
11

我已經使用Java 8幾個月了,而且我已經開始使用Lambda表達式,這對於某些情況非常方便。但是,我經常遇到一些問題,以便對使用Lambda的代碼進行單元測試。使用Java 8的單元測試代碼Lambdas

以一個例子下面的僞代碼:

private Bar bar; 

public void method(int foo){ 
    bar.useLambda(baz -> baz.setFoo(foo)); 
} 

一種方法是隻覈實條通話

verify(bar).useLambda(Matchers.<Consumer<Baz>>.any()); 

但是,通過這樣做,我不考Lambda的代碼。

另外請注意,我不能用的方法和使用方法引用來代替LAMBDA:

bar.useLambda(This::setFooOnBaz); 

因爲我不會對這種方法foo的。 或者至少這是我的想法。

你有過這個問題嗎?我如何測試或重構我的代碼以正確測試它?


編輯

由於我所編碼是一種單元測試,我不希望實例吧,我將使用一個模擬代替。所以我將無法驗證baz.setFoo呼叫。

回答

14

你不能直接單元測試lambda,因爲它沒有名字。除非您有參考,否則無法調用它。

通常的選擇是將lambda重構爲命名方法,並使用產品代碼中的方法引用並通過測試代碼中的名稱調用該方法。正如你注意到的那樣,這種情況不能用這種方式重構,因爲它捕獲foo,唯一可以被方法引用捕獲的是接收器。

answer from yshavit涉及到是否需​​要單元測試私有方法的重要一點。 lambda肯定可以被認爲是一種私人方法。

這裏還有一個更大的問題。單元測試的一個原理就是你不需要單元測試too simple to break的任何東西。這與lambda的理想情況非常吻合,這是一個非常簡單的表達,顯然是正確的。 (至少,這就是我認爲的理想選擇。)考慮例如:

baz -> baz.setFoo(foo) 

是否有這個lambda表達式,當遞給Baz參考任何疑問,會調用它setFoo方法,並把它傳遞foo作爲參數?也許它非常簡單,不需要進行單元測試。

另一方面,這僅僅是一個例子,也許你想測試的實際lambda表達式要複雜得多。我見過使用大型嵌套多行lambda表達式的代碼。例如,請參閱this answer及其問題和其他答案。這樣的lambda確實很難調試和測試。如果lambda中的代碼足夠複雜以至於無法保證測試,那麼也許該代碼應該從lambda中重構出來,以便可以使用常規技術對其進行測試。

+0

當你說我的實際lambda比一組更復雜時,你是對的,但它仍然很簡單,可以認爲它不會中斷。畢竟,也許我只是試圖單元測試100%的代碼,這是根本問題。謝謝! – Fdiazreal 2015-02-24 10:55:11

11

像對待你的私人方法一樣對待lambda表達式;不要單獨測試它,而是測試它的效果。在你的情況下,調用method(foo)應該導致bar.setFoo發生 - 所以,請撥打method(foo),然後驗證bar.getFoo()

+1

同意,不要單元測試lambda;單元測試結果。 – whitfin 2015-02-24 04:21:43

+0

如何驗證'baz.setFoo'沒有實例化bar,因此,使用bar作爲模擬? – Fdiazreal 2015-02-24 04:26:10

+3

@Fdiazreal:因爲你的代碼正在委託給'Bar',所以沒有必要在沒有實例化欄的情況下測試這個動作。當然,你也可以自己測試'baz.setFoo(foo)'。由於'setFoo'是一種普通的方法,所以測試它應該沒有問題 - 只需忘記lambda。 – Holger 2015-02-24 08:47:08