0

Please, help me write a JUnit test for this code using Mockito.

class A{
    private BlockingQueue<Runnable> jobQueue;

    public void methodA(List<String> messages) {
        try {
            jobQueue.put(() -> methodB(message));
        } catch(InterruptedException e) {}
    }

    private void methodB(Message message) {
        //other logic
    }
}
Loïc Le Doyen
  • 975
  • 7
  • 16
dom cobb
  • 25
  • 1
  • 5
  • Why do you want to use Mockito in this case ? Nothing in the code provided seems to require mocking. – Loïc Le Doyen Dec 19 '18 at 10:45
  • here i have mocked the jobqueue.put method call, but flow is not going to MethodB. i wanted to test MethodB, how to test it? – dom cobb Dec 19 '18 at 11:49
  • `BlockingQueue` is just a data structure and I do not see the point of mocking it. As your only public method is placing a `Runnable` in the queue, if you do not execute this `Runnable` somewhere, `methodB` will not be invoked. You lack of some other public method, that takes those stored Runnables and executes them. – Loïc Le Doyen Dec 19 '18 at 13:38

1 Answers1

2

Your example lacks context as to what it is methodB is doing... Without knowing what the functionality is that you want to verify, just verifying that methodB gets called wouldn't be a particularly useful test, nor is mocking the BlockingQueue. I'm going to go out on a limb and assume that methodB interacts with another object, and it's this interaction that you really want to verify, if that's the case my code and test would look something like:

class A {
    private BlockingQueue<Runnable> jobQueue;
    private B b;

    public void methodA(Message message) {
        try {
            jobQueue.put(() -> methodB(message));
        } catch (InterruptedException e) {
        }
    }

    private void methodB(Message message) {
        b.sendMethod(message);
    }
}

class B {
    public void sendMethod(Message message) {
        // other logic
    }
}

And my test would potentially look something like:

class Atest {

    private A testSubject;

    @Mock
    private B b;

    @Test
    public void testASendsMessage() {
        Message message = new Message("HELLO WORLD");
        testSubject.methodA(message);
        verify(b, timeout(100)).sendMethod(message);
    }

    @Before
    public void setup() throws Exception {
        testSubject = new A();
    }
}

In general you want to avoid needing to verifying bits with multiple threads in a unit test, save tests with multiple running threads mainly for integration tests but where it is necessary look at Mockito.timeout(), see example above for how to use. Hopefully this helps?

John Stringer
  • 558
  • 2
  • 6
  • 1
    I'm getting test failed as `Wanted but not invoked: b.sendMethod(message)` and then `Actually, there were zero interactions with this mock` – JackTheKnife Dec 13 '22 at 01:54