6

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?

francoisr
  • 4,407
  • 1
  • 28
  • 48
Boris
  • 443
  • 8
  • 15
  • Where does `message` come from? Is it a field of `SomeClass`, parameter of `method()` or something else? – noscreenname Aug 18 '16 at 12:54
  • In the production code, the dependency produces the message as follows: `toBeMockedDependency.doSomething(Consuner consumer) { ... String message = "... .."; consumer.accept(message); ... }` – Boris Aug 18 '16 at 13:01
  • can you provide full code of when and where from `consumer.accept(message)` is called? – noscreenname Aug 18 '16 at 13:09

1 Answers1

8

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(...);
  }
}
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251