How to unit test Spring Integration’s int-file:inbound-channel-adapter

1k Views Asked by At

I have a simple Spring Integration flow where I read XML files from a given directory, and send their content to another channel and do other processing.

After the processing is done, I need to move the input file in an archive/error directory.

file-integration.xml:

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int-file="http://www.springframework.org/schema/integration/file"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
       http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/integration/file https://www.springframework.org/schema/integration/file/spring-integration-file.xsd
       http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

  <import resource="transaction-manager-configuration.xml"/>

  <context:property-placeholder location="classpath:app.properties"/>

  <int:channel id="inputFileChannel"/>

  <int-file:inbound-channel-adapter channel="inputFileChannel"
                                    directory="${inputDir}"
                                    filename-pattern="*.xml">
    <int:poller fixed-delay="1000">
      <int:transactional transaction-manager="txManager" synchronization-factory="syncFactory"/>
    </int:poller>
  </int-file:inbound-channel-adapter>

  <int-file:file-to-string-transformer input-channel="inputFileChannel"
                                       output-channel="contentChannel"/>

  <int:channel id="contentChannel"/>
  <int:channel id="inputFileSuccessChannel"/>
  <int:channel id="inputFileErrorChannel"/>

  <!-- Move file after being processed -->

  <int:transaction-synchronization-factory id="syncFactory">
    <int:after-commit channel="inputFileSuccessChannel"/>
    <int:after-rollback channel="inputFileErrorChannel"/>
  </int:transaction-synchronization-factory>

  <int-file:outbound-channel-adapter channel="inputFileSuccessChannel"
                                     directory="${archiveDir}"
                                     delete-source-files="true"/>

  <int-file:outbound-channel-adapter channel="inputFileErrorChannel"
                                     directory="${errorDir}"
                                     delete-source-files="true"/>

</beans>

My questions:

  1. In a unit test context, how can I create & push an in-memory file in inputFileChannel, without relying on the real filesystem?
  2. How can I test that my input file has been pushed to inputFileSuccessChannel / inputFileErrorChannel? How to mock the <int-file:outbound-channel-adapter/>?
  3. Again in my unit test context without relying on the real filesystem, how can I test that my in-memory input file has been deleted (as configured with the delete-source-files="true" statements)?

At the moment, I have a JUnit 5 test class FileIntegrationTest.java:

@ExtendWith(SpringExtension.class)
@ContextConfiguration
@PropertySource("classpath:app.properties")
@SpringIntegrationTest
public class FileIntegrationTest {
  @Autowired
  MessageChannel inputFileChannel;

  @Autowired
  QueueChannel contentTestChannel;

  @Test
  void shouldReadInputFile_thenMoveIt() {
    // arrange
    File inputFile = new … // question 1
    Message<File> inputMessage = MessageBuilder.withPayload(file).build();

    // act
    inputFileChannel.send(inputMessage);

    // assert
    assertThat(contentTestChannel.getQueueSize(), is(1));
    assertThat(inputFileSuccessChannel contains my input file); // question 2
    assertThat(inputFile has been deleted); // question 3
  }
}

And its context file FileIntegrationTest-context.xml:

<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:int="http://www.springframework.org/schema/integration"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd">

  <import resource="classpath:/META-INF/spring/integration/file-integration.xml"/>

  <int:bridge input-channel="contentChannel"
              output-channel="contentTestChannel"/>
  <int:channel id="contentTestChannel">
    <int:queue/>
  </int:channel>
</beans>

The official Spring Testing support page mentions the use of mocks, but I’m confused how to use it. I’ve checked out https://github.com/spring-projects/spring-integration-samples as well, but I could find a proper solution.

1

There are 1 best solutions below

6
On
  1. Yes
  2. Add a channel interceptor to the channel, or see the documentation about mocking endpoints.
  3. If you send a test file to the channel; you can check to see if still exists when the test completes.