9

I'm trying to mock a collaborator, named Worker and capture arguments of its method execute which runs in different thread. However, the method itself has method references as arguments: childService::listClients and childService::refreshObjects. When I assert method references with captured arguments, I get different lambda objects.

Is there a way to reach and assert them in proper way?

The class being tested:

public class ParentService {
    private ChildService childService;
    private Worker worker;
    ...
    public void doAction() {
        worker.execute(
                childService::listClients,
                childService::refreshObjects
        );
    }
}

The test:

@Test
public void shouldUseChildService() {
    ArgumentCaptor<Callable> callableCaptor = ArgumentCaptor.forClass(Callable.class);
    ArgumentCaptor<Consumer> consumerCaptor = ArgumentCaptor.forClass(Consumer.class);

    parentService.doAction();

    verify(worker).execute(callableCaptor.capture(), consumerCaptor.capture());
    assertEquals((Callable) childService::listClients, callableCaptor.getValue());
    assertEquals((Consumer) childService::refreshObjects, consumerCaptor.getValue());
}

Assertion error:

    java.lang.AssertionError: 
    Expected :org.app.services.ParentServiceTest$$Lambda$4/990416209@1786dec2
    Actual   :org.app.services.ParentServiceTest$$Lambda$1/1340328248@74650e52
at org.junit.Assert.failNotEquals(Assert.java:743)
    at org.junit.Assert.assertEquals(Assert.java:118)
    at org.junit.Assert.assertEquals(Assert.java:144)
    at org.app.services.ParentServiceTest.shouldUseChildService(ParenServiceTest.java:66)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Admx
  • 105
  • 1
  • 9
  • 1
    This is not a problem of the lambda expression but a conceptual problem. Given two `Callable`, when are they equal? The same for `Consumer`, when are they equal? – Tunaki Jan 15 '16 at 08:47
  • @Tunaki I have edited the second assertion. Do you mean those objects can't be compared with assertTrue? I was also stubbing the childService.listClients() method but the result was the same. – Admx Jan 15 '16 at 08:54
  • 1
    The question is, what do you want to assert? It seems that what you want to do is verify that `listClients` and `refreshObjects` were called, is that right? – Tunaki Jan 15 '16 at 08:57
  • Yes, but to verify if they are called, I have to use assertion. – Admx Jan 15 '16 at 09:02
  • 2
    No, this is typical XY problem. To verify that they are called, you mock `childService` and verify its behaviour with `Mockito.verify`. – Tunaki Jan 15 '16 at 09:03
  • It only seems to be:) `worker.execute` is running in different thread so I have to verify if worker runs execute method with desired arguments. Mocking and verifying `childService` doesn't work. – Admx Jan 15 '16 at 09:08
  • 1
    You could mock the ChildService, mock the worker, make the mock worker.execute() method call its two arguments using a custom Mockito Answer, call your parent service, and verify that listClients() and refreshObjects() have been called on the mocked ChildService. – JB Nizet Jan 15 '16 at 09:19
  • Then I doAnswer(...).when(worker).execute(childService::listClients, childService::refreshObjects) and answer with returning new Client object, but then I still get the same assertion error. – Admx Jan 15 '16 at 14:18

1 Answers1

5

First Mock your Worker with Mockito (just as you did). Also mock your ChildService. Then:

@Test
public void shouldUseChildService() {
  ArgumentCaptor<Callable> callableCaptor = ArgumentCaptor.forClass(Callable.class);
  ArgumentCaptor<Consumer> consumerCaptor = ArgumentCaptor.forClass(Consumer.class);

  parentService.doAction();

  verify(worker).execute(callableCaptor.capture(), consumerCaptor.capture());
  callableCaptor.getValue().call(); //this will execute whatever was captured
  consumerCaptor.getValue().accept(null);//this will execute whatever was captured

  // now verify that childService::listClients and childService::refreshObjects have been called
}
mkobit
  • 43,979
  • 12
  • 156
  • 150
CoronA
  • 7,717
  • 2
  • 26
  • 53