views:

282

answers:

2

Hi,

I want to test an "Adapter" object that when it receives an xml message, it digest it to a Message object, puts message ID + CorrelationID both with timestamps and forwards it to a Client object.=20 A message can be correlated to a previous one (e.g. m2.correlationID =3D m1.ID).

I mock the Client, and check that Adapter successfully calls "client.forwardMessage(m)" twice with first message with null correlationID, and a second with a not-null correlationID.

However, I would like to precisely test that the correlationIDs are set correctly, by grabing the IDs (e.g. m1.ID).

But I couldn't find anyway to do so.

There is a jira about adding the feature, but no one commented and it is unassigned.

Is this really unimplemented?

I read about the alternative of redesigning the Adapter to use an IdGenerator object, which I can stub, but I think there will be too many objects.=20 Don't you think it adds unnecessary complexity to split objects to a so fine granularity?

Thanks, and I appreciate any comments :-)

Tayeb

A: 

You could use a matcher (http://code.google.com/p/hamcrest) to check whether you get the correct arguments passed into your method. Note you'll need to statically import your matcher (HasCorrelationId in my example).

The example below asserts that client.forwardMessage(m) is called once with a message with null correlationId and once with a message with correlationId="abc".

import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;

public class HasCorrelationId extends TypeSafeMatcher<Message> {
    private final Object expectedCorrelationId;
    public HasCorrelationId(Object expectedCorrelationId) {
        this.expectedCorrelationId = expectedCorrelationId;
    }
    @Override
    public boolean matchesSafely(Message message) {
        if (expectedCorrelationId==message.getCorrelationId()) return true;
        return expectedCorrelationId==null? false: expectedCorrelationId.equals(message.getCorrelationId());

    }

    public void describeTo(Description description) {
        description.appendText("hasCorrelationId("+expectedCorrelationId+")");

    }

    public static HasCorrelationId hasCorrelationId(Object correlationId) {    
    return new HasCorrelationId(correlationId);
    }
}

... and now for the test:

public class MyTest {
    private Mockery context = new Mockery();

  @Test
  public void testCorrelationId() {
    final Client client = context.mock(Client.class);
    final Message message1 = context.mock(Message.class,"message1");
    final Message message2 = context.mock(Message.class,"message2");

    context.checking(new Expectations(){{
        allowing(message1).getCorrelationId();will(returnValue(null));
        allowing(message2).getCorrelationId();will(returnValue("abc"));

        one(client).forwardMessage(with(hasCorrelationId(null)));
        one(client).forwardMessage(with(hasCorrelationId("abc")));
    }});

    client.forwardMessage(message1);
    client.forwardMessage(message2);
    }

}
bm212
A: 

We've made some effort to simplify writing matchers in Hamcrest 1.2. There's a new FeatureMatcher which requires less work.

Steve Freeman