2

I have these two lines at different points of my code:

Message<T1> reply = (Message<T1>) template.sendAndReceive(channel1, message);

Message<T2> reply = (Message<T2>) template.sendAndReceive(channel2, message);

I am doing some unit testing and the test covers both statements. When I try to mock the behaviour, I define some behaviour like this:

Mockito.when(template.sendAndReceive(Mockito.any(MessageChannel.class), Matchers.<GenericMessage<T1>>any() )).thenReturn(instance1);

Mockito.when(template.sendAndReceive(Mockito.any(MessageChannel.class), Matchers.<GenericMessage<T2>>any()   )).thenReturn(null);

When I execute the unit tests and do some debugging , the first statement returns null

Do you have any idea what the matchers seem not to work ? and it always takes the last definition of the mock . I am using Mockito 1.1.10

Deibys
  • 619
  • 3
  • 9
  • 18
  • 1
    You're suffering from type erasure. The only thing that's different between the two calls is the generic in the `<>` in `GenericMessage` - they look the same to runtime Java. Best advice is to make the mock's behaviour vary based on the objects you pass in, not their types, then you'll get the behaviour you want. – Ashley Frieze Nov 01 '16 at 23:30

1 Answers1

4

When I execute the unit tests and do some debugging , the first statement returns null

This happened because you did stub the same method invocation twice with thenReturn(..); and the last one with null won.


The proper way to achieve your goal is to provide a list of consecutive return values to be returned when the method is called:

Mockito.when(template.sendAndReceive(Matchers.any(MessageChannel.class), Matchers.any(GenericMessage.class)))
    .thenReturn(instance1, null);

In this case, the returned value for the first invocation will be instance1, and all subsequent invocations will return null. See an example here.


Another option, as Ashley Frieze suggested, would be making template.sendAndReceive return different values based on arguments:

Mockito.when(template.sendAndReceive(Matchers.same(channel1), Matchers.any(GenericMessage.class)))
    .thenReturn(instance1);
Mockito.when(template.sendAndReceive(Matchers.same(channel2), Matchers.any(GenericMessage.class)))
    .thenReturn(null);

Or even shorter, we can omit second line, because default return value for unstubbed mock method invocations is null:

Mockito.when(template.sendAndReceive(Matchers.same(channel1), Matchers.any(GenericMessage.class)))
    .thenReturn(instance1);

Here we are assume that some channel1 and channel2 are in scope of test class and are injected into object under test (at least it seems so from code snippet you provided in the question).

Community
  • 1
  • 1
Mykhailo
  • 1,134
  • 2
  • 17
  • 25
  • I thought about it but I was giving it my last try since this way seems to me the unit test is very coupled with code I want to test – Deibys Nov 02 '16 at 13:29
  • @Deibys, I have added a second option, which does not do any assumptions about the order in which invocations of `template.sendAndReceive` are done. – Mykhailo Nov 02 '16 at 14:21