FTP - neilcatalan/MUnit-Implementation GitHub Wiki
For FTP implementation, I make use of the OOTB Mock FTP local server. By default it makes use the root folder of my local machine or PC. This is super cool because I don't need to write a mock definition, I'll just use the component and it will automatically start when the test starts.
The FTP implementation here is consists of two flows, one with the inbound endpoint and the other has outbound endpoint. Unlike the JMS which points to the same queue, here I decided to point the endpoints to two different folders which are defined in a property file as "ftp.path.outbound" and "ftp.path.inbound". This is necessary because the default behavior of the inbound FTP endpoint is to poll the server every 1000 ms and it will not wait for the outbound endpoint to finish. That scenario is not good if we point the inbound and outbound endpoints to the same folder since there is a chance that the inbound flow will poll to an empty server every 1000 ms since it will not wait for the outbound endpoint to finish; thus it may lead to unit test failure.
<flow name="ftpInboundFlow" >
<ftp:inbound-endpoint host="${ftp.host}" port="${ftp.port}" path="${ftp.path.inbound}" user="${ftp.user}" password="${ftp.password}" responseTimeout="10000" doc:name="FTP_Listener">
</ftp:inbound-endpoint>
<logger message="#["PRINT FTP INBOUND PAYLOAD: "+payload]" level="INFO" doc:name="Logger"/>
</flow>
<flow name="ftpOutboundFlow" >
<ftp:outbound-endpoint outputPattern="${ftp.pattern}" responseTimeout="10000" doc:name="FTP_Sender" host="${ftp.host}" password="${ftp.password}" path="${ftp.path.outbound}" port="${ftp.port}" user="${ftp.user}"/>
<logger message="#["PRINT FTP OUTBOUND PAYLOAD: "+payload]" level="INFO" doc:name="Logger"/>
</flow>
The test suite consists of two test cases see below config file; for testing the inbound flow I make sure that I create first a sample file using a groovy script, then after that I execute Thread.sleep(5000) this is to wait for the FTP inbound endpoint to reconnect and poll again the local server. This is necessary because I noticed that FTP inbound endpoint starts to poll even the test suites is not yet started. I believe Mule ESB will start first then unit test will proceed in Anypoint Studio. The last test case just invoke the outbound flow and it will create a file to the Mock FTP Server. After executing the test cases, the test suite will execute a groovy file that I created to delete files from my local machine.
<munit:config mock-inbounds="false" mock-connectors="false" doc:name="MUnit configuration"/>
<ftpserver:config port="${ftp.port}" name="ftpServer" doc:name="FTP Server"/>
<spring:beans>
<spring:import resource="classpath:globalconfig.xml"/>
<spring:import resource="classpath:ftp.xml"/>
</spring:beans>
<munit:before-suite name="ftp-test-suiteBefore_Suite" description="MUnit Test">
<scripting:component doc:name="Create sample dir and files on mock local FTP Server">
<scripting:script engine="Groovy" file="generateDirAndFile.groovy">
<property key="inDir" value="${ftp.path.inbound}"/>
<property key="outDir" value="${ftp.path.outbound}"/>
<property key="filePattern" value="${ftp.pattern}"/>
</scripting:script>
</scripting:component>
<ftpserver:start-server config-ref="ftpServer" doc:name="Start Mock Local FTP Server"/>
</munit:before-suite>
<munit:test name="ftp-test-Inbound-suiteTest" description="MUnit Test">
<expression-component doc:name="Wait 5 seconds for file polling and reading from FTP Server to finish"><![CDATA[Thread.sleep(5000);]]></expression-component>
</munit:test>
<munit:test name="ftp-test-Outbound-suiteTest" description="Test">
<munit:set payload="#["This is a sample outbound message"]" doc:name="Set Message"/>
<flow-ref name="ftpOutboundFlow" doc:name="ftpOutboundFlow"/>
<!-- <flow-ref name="ftpOutboundFlow" doc:name="ftpOutboundFlow"/> -->
</munit:test>
<munit:after-suite name="ftp-test-suiteAfter_Suite" description="Ater suite actions">
<ftpserver:stop-server config-ref="ftpServer" doc:name="Stop Mock Local FTP Server"/>
<scripting:component doc:name="Delete sample dir and files on mock local FTP Server">
<scripting:script engine="Groovy" file="deleteDirAndFile.groovy">
<property key="inDir" value="${ftp.path.inbound}"/>
<property key="outDir" value="${ftp.path.outbound}"/>
<property key="filePattern" value="${ftp.pattern}"/>
</scripting:script>
</scripting:component>
</munit:after-suite>