简体   繁体   English

Camel Unmarshal CSV 测试结果不同

[英]Camel Unmarshal CSV with different results in test

I'm unmarshalling a csv file in my route, but the actual application and the tests are giving me different results.我在我的路由中解组 csv 文件,但实际应用程序和测试给了我不同的结果。 This is the code:这是代码:

 from("direct:start")
    .routeId("report")
    .pollEnrich("file:///Users/xxx/csv")
    .log(LoggingLevel.INFO, " File detected: ${header.CamelAwsS3Key}")
    .unmarshal()
    .csv()
    .convertBodyTo(String.class)
    .process(new Processor() {
      @Override
      public void process(Exchange exchange) throws Exception {

        List<String> ids = exchange.getIn().getBody(List.class);

In the application execution the expression exchange.getIn().getBody() returns b3e486c6-635b-4383-955c-06934ae6e5e4,00f8757a-baac-409d-bc6f-13e90aa75361 which is the expected result that I can convert to a list.在应用程序执行中,表达式exchange.getIn().getBody()返回b3e486c6-635b-4383-955c-06934ae6e5e4,00f8757a-baac-409d-bc6f-13e90aa75361这是我可以转换为列表的预期结果。

But in the test the same expression returns [[b3e486c6-635b-4383-955c-06934ae6e5e4], [00f8757a-baac-409d-bc6f-13e90aa75361]] , a list of lists.但在测试中,相同的表达式返回[[b3e486c6-635b-4383-955c-06934ae6e5e4], [00f8757a-baac-409d-bc6f-13e90aa75361]]列表列表。 Then the conversion List<String> ids = exchange.getIn().getBody(List.class);然后转换List<String> ids = exchange.getIn().getBody(List.class); returns null .返回null

The unit test code is a simple use case:单元测试代码是一个简单的用例:

    @ExtendWith(MockitoExtension.class)
class RouteBuilderTest extends CamelTestSupport {
 @Test
  void sendReport() throws Exception {
    
    context.start();
    template.sendBody("direct:report", null);
  }

}

What could be causing this behaviour?什么可能导致这种行为?

I'm unmarshalling a csv file in my route, but the actual application and the tests are giving me different results.我在我的路由中解组 csv 文件,但实际应用程序和测试给了我不同的结果。

It's much more likely that you're simply reading different file.您更有可能只是在阅读不同的文件。 The.log(LoggingLevel.INFO, " File detected: ${header.CamelAwsS3Key}") part makes me question the if you're even using the same RouteBuilder in your actual application. The.log(LoggingLevel.INFO, " File detected: ${header.CamelAwsS3Key}") 部分让我质疑您是否在实际应用程序中使用相同的 RouteBuilder。

Try checking out the body before marshalling it to see if its really the Camel CSV Unmarshal giving you the trouble or if the file contents are different or if it's the consumer endpoint that is acting differently.在编组之前尝试检查正文,看看它是否真的是 Camel CSV Unmarshal 给您带来麻烦,或者文件内容是否不同,或者是否是消费者端点的行为不同。

rom("direct:start")
    .routeId("report")
    .pollEnrich("file:///Users/xxx/csv")
    // To allow us to read body multiple times
    .convertBodyTo(String.class)
    // Display contents of the file 
    .log("file contents: \n ${body}")
    .unmarshal()
    .csv()
    // ...

Unit testing, folder and files单元测试、文件夹和文件

When it comes to unit testing applications that read files from folders you should avoid using hard coded paths.当涉及从文件夹读取文件的单元测试应用程序时,您应该避免使用硬编码路径。 Contents of these paths can change at any moment which will invalidate the test.这些路径的内容可以随时更改,这将使测试无效。

There's also the fact that camels file component will by default move processed files to hidden .camel folder so the file wont be consumed again.还有一个事实是骆驼文件组件默认情况下会将处理过的文件移动到隐藏的.camel文件夹中,这样文件就不会被再次使用。 Even with noop option set to true camel will keep track of which files have been already consumed using in-memory registry.即使 noop 选项设置为 true camel 也会使用内存注册表跟踪哪些文件已经被使用。

Instead you should create temporary directory and copy files from test resources to said directory for testing.相反,您应该创建临时目录并将文件从测试资源复制到所述目录以进行测试。 Both Junit4 and Junit5 come with Temporary folder feature and you can use Apache Commons IO to quickly copy test resources to said folder. Junit4 和 Junit5 都带有临时文件夹功能,您可以使用 Apache Commons IO 快速将测试资源复制到所述文件夹。

Example: Apache Camel 3.18.1示例:Apache 骆驼 3.18.1

package com.example;

import java.io.File;
import java.util.Properties;

import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Example extends CamelTestSupport {
    
    static final Logger LOGGER = LoggerFactory.getLogger(InputOutputFileRoutesTests.class);

    @TempDir
    File inputFolder;

    @Test
    public void readFileExampleTest() throws Exception {
        
        copyResourceFileToInputFolder("HelloWorld.txt");
        MockEndpoint resultMockEndpoint = getMockEndpoint("mock:result");
        
        resultMockEndpoint.expectedMessageCount(1);
        resultMockEndpoint.message(0).equals("Hello World!");

        template.sendBody("direct:readFileExample", null);

        resultMockEndpoint.assertIsSatisfied();
    }

    @Override
    protected RoutesBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {

            @Override
            public void configure() throws Exception {

                from("direct:readFileExample")
                    .routeId("readFileExample")
                    .pollEnrich("file:{{input.path}}")
                    .convertBodyTo(String.class)
                    .log("Body is: ${body}")
                    .to("mock:result");
            }
        };
    }

    private void copyResourceFileToInputFolder(String resourceName){

        ClassLoader classLoader = InputOutputFileRoutesTests.class.getClassLoader();
        File resourceFile = new File(classLoader.getResource(resourceName).getFile());
        File testFile = new File(inputFolder, resourceName);

        try {
            FileUtils.copyFile(resourceFile, testFile);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
    }
    
    @Override
    protected Properties useOverridePropertiesWithPropertiesComponent() {

        Properties properties = new Properties();
        properties.put("input.path", inputFolder.getPath());
        return properties;
    }
}

Apache Commons IO dependency. Apache Commons IO 依赖。

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
    <scope>test</scope>
</dependency>

As side note pollEnrich with adviceWith is pretty nice for testing routes that use polling consumer endpoint like camel-file or camel-ftp.作为旁注,pollEnrich 和adviceWith 非常适合测试使用轮询消费者端点(如camel-file 或camel-ftp)的路由。

@Test
public void readFileExampleTest() throws Exception {
    
    AdviceWith.adviceWith(context(), "readFileExample", a -> {

        a.replaceFromWith("direct:readFileExample");
        a.weaveAddFirst()
            .pollEnrich("file:{{input.path}}");

        a.weaveAddLast()
            .to("mock:result");
    });

    copyResourceFileToInputFolder("HelloWorld.txt");

    MockEndpoint resultMockEndpoint = getMockEndpoint("mock:result");        
    resultMockEndpoint.expectedMessageCount(1);
    resultMockEndpoint.message(0).equals("Hello World!");

    startCamelContext();
    template.sendBody("direct:readFileExample", null);

    resultMockEndpoint.assertIsSatisfied();
}

@Override
public boolean isUseAdviceWith() {
    return true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM