我希望我的模拟器在调用10次时返回method1()
并在之后调用时返回method2()
。下面的代码适用于匿名内部类。在Java 8中有一种优雅的方法吗?
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();
}
}
);
答案 0 :(得分: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());
再次考虑它,有一个解决方案在代码方面并不简单,但如果第一次调用的数量很大,则更可取:
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()));
答案 1 :(得分:1)
Answer
是一个单方法接口,因此您可以简化匿名内部类样板。除非您将其提取到您编写的方法(例如firstNTimes(invocation -> method1(), 10, invocation -> method2())
),否则我认为没有任何内置的替代方法可以简化您的逻辑。
when(mock.doSomething()).thenAnswer(invocationOnMock -> {
if (count < 10) {
count++;
return method1();
}
return method2();
});
我没有机会测试这个;如果Throwable
或答案泛型会给您带来任何麻烦,请发表评论,我会再看看。