use*_*471 6 java mockito java-8
我正在尝试测试一个带Consumer函数的方法,我想用Mockito验证我的lambda表达式只被调用一次.我现在使用的是在最终的单元素数组上使用标志的那种笨重方式:
final boolean[] handlerExecuted = {false};
instance.conditionalRun(item -> {
handlerExecuted[0] = true;
item.foo();
});
Assert.assertTrue(
"Handler should be executed.",
handlerExecuted[0]);
Run Code Online (Sandbox Code Playgroud)
看起来应该有更好的方法(或许是Mockito间谍)来验证这个lambda表达式只被调用一次.
其他一些答案提供了完全按照我的要求做出选择的替代方法,但这可以通过Consumer窥探类本身并让间谍调用你真正想要执行的方法来实现.包裹lambda以创建间谍的辅助方法有助于:
/** Get a spied version of the given Consumer. */
private Consumer<Item> itemHandlerSpy(Consumer<Item> itemHandler) {
// Create a spy of the Consumer functional interface itself.
@SuppressWarnings("unchecked")
Consumer<Item> spy = (Consumer<Item>) Mockito.spy(Consumer.class);
// Tell the spy to run the given consumer when the Consumer is given something to consume.
Mockito.doAnswer(it -> {
// Get the first (and only) argument passed to the Consumer.
Item item = (Item) it.getArguments()[0];
// Pass it to the real consumer so it gets processed.
itemHandler.accept(item);
return null;
}).when(spy).accept(Mockito.any(Item.class));
return spy;
}
Run Code Online (Sandbox Code Playgroud)
然后测试方法变得非常简单:
Consumer<Item> itemHandler = itemHandlerSpy(Item::foo);
instance.conditionalRun(itemHandler);
// This verifies conditionalRun called the Consumer exactly once.
Mockito.verify(itemHandler).accept(Mockito.any(Item.class));
Run Code Online (Sandbox Code Playgroud)