問題描述
我有一個接口 Foo
和方法 int Foo.bar(int)
我想用 Mockito 模擬.如果我傳入 1
,我希望模擬方法返回 99
,但所有其他值都會引發(fā)異常.我可以這樣做嗎?
I have an interface Foo
with method int Foo.bar(int)
that I want to mock with Mockito. I want the mocked method to return 99
if I pass in 1
, but all other values will throw an exception. Can I do this?
final Foo foo = mock(Foo.class);
when(foo.bar(1)).thenReturn(99);
when(foo.bar(anyInt())).thenThrow(new IllegalArgumentException());
換句話說,1
會優(yōu)先于 anyInt()
嗎?我不希望它為 1
拋出異常.docs 說對于多個定義,最后一個定義更重要,但我不知道這是否意味著相同的論點.如果在這里適用,我需要先定義通配符 anyInt()
嗎?或者兩者是否有任何關(guān)系,因為其中一個是匹配器,另一個只是一個值?
In other words, will the 1
take precedence over anyInt()
? I wouldn't want it throwing an exception for 1
. The docs say that for multiple definitions the last definition is more important, but I couldn't tell if that meant for identical arguments or not. If it applies here, would I need to define the wildcard anyInt()
first? Or do the two even have any relation, as one of them is a matcher and the other is just a value?
推薦答案
您有兩個選擇:匹配除一個之外的任何值",以及覆蓋存根.(我想您也可以將 Answer 用于復雜的自定義行為,但對于這種情況來說,這太過分了.)
You have two options: Matching "any value but one", and overriding stubbing. (I suppose you could also use an Answer for complex custom behavior, but that's overkill for situations like this one.)
Mockito 的 AdditionalMatchers
類提供了許多有用的匹配器,包括操作符,例如 不是
.這將允許您為除特定值(或表達式)之外的所有值設(shè)置行為.
Mockito's AdditionalMatchers
class offers a number of useful matchers, including operators such as not
. This would allow you to set behavior for all values except for a specific value (or expression).
when(foo.bar(1)).thenReturn(99);
when(foo.bar(not(eq(1)))).thenThrow(new IllegalArgumentException());
請注意,運算符必須與匹配器而不是值一起使用,由于 Mockito 的 Matchers.eq 作為顯式 equals
匹配器"https://stackoverflow.com/a/22822514/1426891">參數(shù)匹配器堆棧:
Be careful to note that operators must be used with matchers instead of values, possibly requiring Matchers.eq
as an explicit equals
matcher, due to Mockito's argument matcher stack:
/* BAD */ when(foo.bar(not( 1 ))).thenThrow(new IllegalArgumentException());
/* GOOD */ when(foo.bar(not(eq(1)))).thenThrow(new IllegalArgumentException());
覆蓋存根
對于存根,最后定義的匹配鏈獲勝.這允許您在 @Before
方法中設(shè)置一般測試夾具行為,并根據(jù)需要在單個測試用例中覆蓋它,但也意味著在您的存根調(diào)用中順序很重要.
Overriding stubbing
For stubbing, the last-defined matching chain wins. This allows you to set up general test fixture behavior in a @Before
method and override it in individual test cases if you wish, but also implies that order matters in your stubbing calls.
when(foo.baz(anyInt())).thenReturn("A", "B"); /* or .thenReturn("A").thenReturn("B"); */
when(foo.baz(9)).thenReturn("X", "Y");
foo.baz(6); /* "A" because anyInt() is the last-defined chain */
foo.baz(7); /* "B" as the next return value of the first chain */
foo.baz(8); /* "B" as Mockito repeats the final chain action forever */
foo.baz(9); /* "X" because the second chain matches for the value 9 */
foo.baz(9); /* "Y" forever because the second chain action still matches */
因此,您永遠不會看到問題中列出的順序中的兩個存根,因為如果一般匹配緊跟特定匹配,則永遠不會使用特定匹配(也可能被刪除).
Consequently, you should never see the two stubs in the order listed in the question, because if a general match immediately follows a specific match then the specific match will never be used (and may as well be deleted).
請注意,在覆蓋間諜或危險的存根行為時,您有時需要將語法更改為 doAnswer
.Mockito 知道不計算對 when
的調(diào)用以進行驗證或沿 thenVerb
鏈前進,但異常仍可能導致您的測試失敗.
Beware that you'll sometimes need to change syntax to doAnswer
when overriding spies or dangerous stubbed behavior. Mockito knows not to count calls to when
for verification or for advancing along thenVerb
chains, but exceptions could still cause your test to fail.
/* BAD: the call to foo.bar(1) will throw before Mockito has a chance to stub it! */
when(foo.bar(anyInt())).thenThrow(new IllegalArgumentException());
when(foo.bar(1)).thenReturn(99);
/* GOOD: Mockito has a chance to deactivate behavior during stubbing. */
when(foo.bar(anyInt())).thenThrow(new IllegalArgumentException());
doReturn(99).when(foo).bar(1);
這篇關(guān)于如何處理“任何其他價值"?與 Mockito?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!