2016-09-15 79 views
2

我想我的模擬返回method1()時調用10次,並返回method2()之後調用。下面的代碼使用匿名內部類。 Java 8中有這樣一個優雅的方法嗎?同樣的答案10次爲一個模擬調用,然後另一個答案後,與Mockito

when(mock.doSomething()).thenAnswer(
    new Answer<Account>() { 
     private int count = 0; 

     @Override 
     public Account answer(InvocationOnMock invocationOnMock) throws Throwable { 
      if (count < 10) { 
       count++; 
       return method1(); 
      } 
      return method2(); 
     } 
    } 
); 

回答

3

由於像計數器和Java 8的lambda表達式這樣的可變狀態不能很好地協同工作,所以沒有直接的,具有計數器的Java 8特定解決方案。而每一次嘗試找到一個巧妙的變通辦法會比以下,無反解

public static <T> OngoingStubbing<T> switchAfter(
       OngoingStubbing<T> stub, int calls, Supplier<T> first, Supplier<T> then) { 
    Answer<T> a1=x -> first.get(), a2=x -> then.get(); 
    while(calls-->0) stub=stub.then(a1); 
    return stub.then(a2); 
} 

糟糕的是使用的只是相當於

Mockito.when(mock.doSomething()).then(x -> method1()).then(x -> method1()) 
     .then(x -> method1()).then(x -> method1()).then(x -> method1()).then(x -> method1()) 
     .then(x -> method1()).then(x -> method1()).then(x -> method1()).then(x -> method1()) 
     .then(x -> method2()); 

可用作

switchAfter(Mockito.when(mock.doSomething()), 10,() -> method1(),() -> method2()); 

又想一想,有一種解決方案在代碼方面並不簡單,但最好如果co UNT首先調用的是大:

public static <T> Answer<T> switchAfter(int calls, Supplier<T> first, Supplier<T> then) { 
    Iterator<T> it=Stream.concat(
      IntStream.range(0, calls).mapToObj(i -> first.get()), 
      Stream.generate(then)) 
     .iterator(); 
    return x -> it.next(); 
} 

可用作

Mockito.when(mock.doSomething()).then(switchAfter(10,() -> method1(),() -> method2())); 
+0

不錯!感謝您的解決方案。 –

1

Answer是單方法的界面讓你可能能夠簡化匿名內部類樣板。我不認爲有任何內置的替代方案可以簡化您的邏輯,除非您將其提取到您編寫的方法(如firstNTimes(invocation -> method1(), 10, invocation -> method2()))。

when(mock.doSomething()).thenAnswer(invocationOnMock -> { 
    if (count < 10) { 
    count++; 
    return method1(); 
    } 
    return method2(); 
}); 

我沒有機會測試這個;如果Throwable或答案泛型給您帶來麻煩,請發表評論,我會再看一次。

+1

你躲過count'的'所需的聲明。因爲這是行不通的,如果count是一個局部變量,它必須在其他地方聲明... – Holger

+0

是的,這不會工作,因爲我們正在改變計數聲明一些最終的地方,它會引發編譯錯誤。 –

+0

@Holger真,儘管你可以很容易地對一個可變對象(如AtomicInteger)進行'final'引用來跟蹤計數,但我同意這使得它看起來不像人們所希望的那麼簡潔。 –

相關問題