2
votes

Trying to figure out how to best unit test an http:outbound-gateway in a Spring Integration workflow.

Here's what our gateway looks like:

<int-http:outbound-gateway id="gateway"
                           request-channel="registrationQueue"
                           message-converters="jsonMessageConverter"
                           url-expression="@urlGenerator.resolve()"
                           http-method="POST"
                           expected-response-type="javax.ws.rs.core.Response"
                           reply-channel="nullChannel"
                           error-handler="httpResponseErrorHandler"/>

Specifically, we want to..

  1. Assert serialization of the objects being sent; do the message-converters correctly process messages coming from the request-channel?
  2. Verify response handling from the 3rd party service; what is the behavior given various responses (expected & unexpected) and errors (internal & external)?

We've got a number of unit tests that mock out the end points and assert the steps of our integration workflow behave as expected. Something like the following:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:test-config.xml"})
public class FileRegistrationWorkflowTest {

    ...

    @Autowired
    private MessageChannel fileFoundChannel;

    @Autowired
    private QueueChannel testRegistrationQueue;

    ...

    @Test
    public void shouldQueueRegistrationForFileWithEntityId() {
        // Given
        mockFileLookupService(FILE_ID, FILENAME_WITH_ENTITY_ID);
        // When
        fileFoundChannel.send(MessageBuilder.withPayload(FILE_ID).build());
        // Then
        Message<?> message = testRegistrationQueue.receive();
        assertThat(message, hasPayload(expected));
    }

}

This method of testing works great for the steps along the workflow. Our trouble is testing the the end point gateways..

  • We can't mock the http:outbound-gateway, then we aren't testing it.
  • We don't want to deploy a real HTTP service to interact with, that's more an integration test.
  • The 3rd party service is only resolved by the url-expression, so there isn't a Spring bean to mock out.

Perhaps we can intercept the HTTP request Spring tries to send?

1

1 Answers

3
votes

In the framework tests we use a DirectFieldAccessor to replace the endpoint's RestTemplate with a mock (actually a stub). However, this doesn't test the converters.

You can get even more sophisticated, where the real RestTemplate can be tested; just get a reference to it (with the SI TestUtils.getPropertyValue() or a DirectFieldAccessor) and configure it as discussed in the Spring Framework documentation.

You can get a reference to the handler with bean name endpointId.handler.