Dave G
Dave G

Reputation: 9777

Testing spring-integration flow using Http.outboundGateway() with configured RestTemplate

I have a situation where I'm writing unit tests for an IntegrationFlow that relies on a configure RestTemplate that does authentication.

@Configuration
public class XXIntegrationConfig {
    @Autowired
    private RestTemplate restTemplate;

    @Bean
    public IntegrationFlow readRemote() {
        return f ->
            f.handle(
                Http.outboundGateway("http://localhost:8080/main/{mainId}", restTemplate)
                    .httpMethod(HttpMethod.GET)
                    .uriVariable("mainId", "headers.mainId")
                    .expectedResponseType(String.class)
            )
            .transformers(Transformers.fromJson())
            .enrich(enrichSecondary())
            .transform(Transformers.toJson());
    }

    @Bean
    public Consumer<EnricherSpec> enrichSecondary() {
        return e ->
            e.requestSubFlow(
                esf -> esf.handle(
                    Http.outboundGateway("http://localhost:8080/main/{mainId}/secondary", restTemplate)
                        .httpMethod(HttpMethod.GET)
                        .uriVariable("mainId", "headers.mainId")
                        .mappedResponseHeaders()
                        .expectedResponseType(String.class)
                )
                .transform(Transformers.fromJson())
            )
            .propertyExpression("secondary", "payload.value");
    }
}

I am having difficulty establishing the test where the restTemplate that is @Autowired is a Mock.

I have tried something similar to the following with no success

@SpringBootTest
@SpringIntegrationTest
public class XXIntegrationConfigTests {
    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    @Autowired
    private XXIntegrationConfig xxIntegrationConfig;

    @Autowired
    private IntegrationFlowContext integrationFlowContext;

    @Test
    public void testEnrichSecondary() {
        when(restTemplate.exchange(..... arg matchers ....)).thenReturn(
              new ResponseEntity("test document", HttpStatus.OK)
        );

        final Consumer<EnricherSpec> enrichSecondary = xxIntegrationConfig.enrichSecondary();
        IntegrationFlow flow =
            f -> f.enrich(enrichSecondary());
        IntegrationFlowContext.IntegrationFlowRegistration flowRegistration =
            integrationFlowContext.registration(flow).register();

        final Message<?> request =
                MessageBuilder.withPayload(new HashMap<String,Object>())
                        .setHeader("mainId", "xx-001")
                        .build();

        Message<?> response = 
                flowRegistration.getMessagingTemplate().sendAndReceive(request); 
    }
}

This testing does not seem to override the injected RestTemplate on the config class before the beans are constructed in XXIntegrationConfig.

Any thoughts on this would be greatly appreciated.

Upvotes: 2

Views: 339

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121542

See Spring Boot's @MockBean: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing.spring-boot-applications.mocking-beans. So, what you need is just mark your RestTemplate property in the test with this annotation and Spring Boot will take care for you about its injection in the expected configurations.

Upvotes: 2

Related Questions