Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With Mockito, how do I verify my lambda expression was called?

I am trying to test a method that takes a Consumer function, and I want to verify with Mockito that my lambda expression is called exactly once. What I'm using now is the kind of clunky way of using a flag on a final, single-element array:

final boolean[] handlerExecuted = {false};
instance.conditionalRun(item -> {
  handlerExecuted[0] = true;
  item.foo();
});

Assert.assertTrue(
    "Handler should be executed.",
    handlerExecuted[0]);

It seems like there should be a better way (with a Mockito spy, perhaps) to verify that this lambda expression was called exactly once.

like image 238
user108471 Avatar asked May 23 '17 20:05

user108471


2 Answers

Some of the other answers offer alternatives to doing exactly what I want here, but this is doable by Spying the Consumer class itself and having the spy call the method you really want to execute. A helper method for wrapping the lambda to create the spy helps here:

/** 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;
}

And then the test method becomes very straightforward:

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));
like image 127
user108471 Avatar answered Oct 18 '22 23:10

user108471


You can verify that your method was called with any lambda expression was called like this:

    verify(someClass).myMethodThatExpectsALambda(any())

    private fun <T> any(): T {
        Mockito.any<T>()
        return null as T
    }
like image 1
Blundell Avatar answered Oct 19 '22 00:10

Blundell