Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 326
Boris Avatar asked Aug 18 '16 11:08

Boris


1 Answers

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(...);
  }
}
like image 67
Jeff Bowman Avatar answered Oct 06 '22 00:10

Jeff Bowman