Search code examples
javaspringunit-testingjunitspring-integration

How to test MessageChannel in Spring Integration?


I'm trying to know if the message passed through specific channel for test or i'd like to get the message from specific channel

So my flow is: controller -> gateway -> ServiceActivator

    private final Gateway gateway;
    public ResponseEntity<Map<String,String>> submit(String applicationId, ApplicationDto applicationDto) {
    applicationDto.setApplicationId(applicationId);
    gateway.submitApplication(applicationDto);
    return ResponseEntity.ok(Map.of(MESSAGE, "Accepted submit"));
    }

the gateway

@Gateway(requestChannel = "submitApplicationChannel", replyChannel = "replySubmitApplicationChannel")
WorkflowPayload submitApplication(ApplicationDto applicationDto);

pipeline

@Bean
MessageChannel submitApplicationChannel() {
    return new DirectChannel();
}

So my test is sending a request to start the flow

@Test
@DisplayName("Application Submission")
void submissionTest() throws Exception {
    
    mockMvc.perform(MockMvcRequestBuilders
            .post("/api/v1/applications/contract-validation/" + APPLICATION_ID)
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(payload)))
            .andExpect(status().isAccepted())
            .andReturn();

//Check HERE if the message passed through the channel

}

Can you give me a hand??


Solution

  • In your test, add a ChannelInterceptor to the submitApplicationChannel before calling the gateway.

    public interface ChannelInterceptor {
    
        /**
         * Invoked before the Message is actually sent to the channel.
         * This allows for modification of the Message if necessary.
         * If this method returns {@code null} then the actual
         * send invocation will not occur.
         */
        @Nullable
        default Message<?> preSend(Message<?> message, MessageChannel channel) {
            return message;
        }
    
        /**
         * Invoked immediately after the send invocation. The boolean
         * value argument represents the return value of that invocation.
         */
        default void postSend(Message<?> message, MessageChannel channel, boolean sent) {
        }
    
        /**
         * Invoked after the completion of a send regardless of any exception that
         * have been raised thus allowing for proper resource cleanup.
         * <p>Note that this will be invoked only if {@link #preSend} successfully
         * completed and returned a Message, i.e. it did not return {@code null}.
         * @since 4.1
         */
        default void afterSendCompletion(
                Message<?> message, MessageChannel channel, boolean sent, @Nullable Exception ex) {
        }
    
        /**
         * Invoked as soon as receive is called and before a Message is
         * actually retrieved. If the return value is 'false', then no
         * Message will be retrieved. This only applies to PollableChannels.
         */
        default boolean preReceive(MessageChannel channel) {
            return true;
        }
    
        /**
         * Invoked immediately after a Message has been retrieved but before
         * it is returned to the caller. The Message may be modified if
         * necessary; {@code null} aborts further interceptor invocations.
         * This only applies to PollableChannels.
         */
        @Nullable
        default Message<?> postReceive(Message<?> message, MessageChannel channel) {
            return message;
        }
    
        /**
         * Invoked after the completion of a receive regardless of any exception that
         * have been raised thus allowing for proper resource cleanup.
         * <p>Note that this will be invoked only if {@link #preReceive} successfully
         * completed and returned {@code true}.
         * @since 4.1
         */
        default void afterReceiveCompletion(@Nullable Message<?> message, MessageChannel channel,
                @Nullable Exception ex) {
        }
    
    }