Search code examples
unit-testingmockitofunctional-interface

Unit testing callback based on Consumer functional interface


I'm trying to unit test code that runs as callback in a Consumer functional interface.

@Component
class SomeClass {

  @Autowired
  private SomeInteface toBeMockedDependency;

  public method() {
     toBeMockedDependency.doSomething(message -> {
        // Logic under test goes here 
        //             (implements java.util.function.Consumer interface)
        ...
     });
  }
}

@RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
  @InjectMocks
  private SomeClass someClass;
  @Mock
  private SomeInteface toBeMockedDependency;

  @Test
  public void testMethod() {
    ...
    someClass.method();
    ...
  }
}

Essentially I want to provide the tested code some tested "message" via "toBeMockedDependency".

How can the "toBeMockedDependency" be mocked to provide a predefined message?
Is it the right approach?


Solution

  • Don't try to make toBeMockedDependency automatically call your functional interface. Instead, use a @Captor to capture the anonymous functional interface, and then use your test to manually call it.

    @RunWith(MockitoJUnitRunner.class)
    public class SomeClassTest {
      @InjectMocks
      private SomeClass someClass;
      @Mock
      private SomeInteface toBeMockedDependency;
      @Captor
      private ArgumentCaptor<Consumer<Message>> messageConsumerCaptor;
    
      @Test
      public void testMethod() {
        someClass.method();
        verify(toBeMockedDependency).doSomething(messageConsumerCaptor.capture());
        Consumer<Message> messageConsumer = messageConsumerCaptor.getValue();
    
        // Now you have your message consumer, so you can test it all you want.
        messageConsumer.accept(new Message(...));
        assertEquals(...);
      }
    }