Camel 单元测试

例1:移动文件

路由设计

从一个文件夹移动文件到另外一个文件夹

package com.learncamel.file;
import org.apache.camel.builder.RouteBuilder;
public class CopyFilesRoute extends RouteBuilder {
    public void configure() throws Exception{
        from("file:data/input?noop=true")
                .to("file:data/output");
    }
}
1
2
3
4
5
6
7
8

测试用例

在下面的示例中,CopyFileRouteTest类将继承CamelTestSupport并覆盖createRouteBuilder方法。 此方法将创建上面定义的路径CopyFilesRoute。


package com.learncamel.file;
import java.io.File;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
public class CopyFileRouteTest extends CamelTestSupport {
    @Override
    protected RoutesBuilder createRouteBuilder() throws Exception {
        return new CopyFilesRoute();
    }
    @Test
    public void checkFileExistsInOutputDirectory() throws InterruptedException
    {
        Thread.sleep(5000);
        File file = new File("data/output");
        assertTrue(file.isDirectory());
        assertEquals(2,file.listFiles().length);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

上面的代码定义了方法checkFileExistsInOutputDirectory(),这个测试用例将检查输出目录是否存在以及移动到输出目录的文件数是2。

例2:direct路由

路由设计

在这里,我们将开发一个带有direct组件的简单路由。direct组件在生产者发送消息交换时提供任一消费者的直接,同步调用。

package com.learncamel.direct;
import org.apache.camel.builder.RouteBuilder;
public class SampleDirectRoute extends RouteBuilder{
    public void configure() throws Exception
    {
        from("direct:sampleInput")
                .log("Received Message is ${body} and Headers are ${headers}")
                .to("file:sampleOutput?fileName=output.txt");
    }
}
1
2
3
4
5
6
7
8
9
10

测试用例

测试用例将检查文件是否是目录,它将验证文件名。

package com.learncamel.direct;
import org.apache.camel.Exchange;
import org.apache.camel.Route;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
import java.io.File;
public class SampleDirectRouteTest extends CamelTestSupport {
    @Override
    public RouteBuilder createRouteBuilder() throws Exception
    {
        return new SampleDirectRoute();
    }
    @Test
    public void SampleTestRoute() throws InterruptedException{
	     //设置消息,template是测试类内置的Producer
        template.sendBody("direct:sampleInput","Hello");
        Thread.sleep(5000);
        File file=new File("sampleOutput");
        assertTrue(file.isDirectory());
        Exchange exchange = consumer.receive("file:sampleOutput");
        System.out.println("Received body is :" + exchange.getIn().getBody());
        System.out.println("File Name is :" + exchange.getIn().getHeader("CamelFileName"));
        assertEquals("output.txt", exchange.getIn().getHeader("CamelFileName"));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

例3:模拟路由

路由设计


package com.learncamel.direct;
import org.apache.camel.builder.RouteBuilder;
public class SampleMockRoute extends RouteBuilder {
    public void configure() throws Exception {
        from("direct:sampleInput")
                .log("Received Message is ${body} and Headers are ${headers}")
                .to("mock:output");
    }
}
1
2
3
4
5
6
7
8
9
10

测试用例

package com.learncamel.direct;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.apache.camel.Exchange;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
import java.io.File;
public class SampleMockRouteTest extends CamelTestSupport {
    @Override
    public RoutesBuilder createRouteBuilder() throws Exception {
        return new SampleMockRoute();
    }
    @Test
    public void sampleMockTest() throws InterruptedException {
        String expected="Hello";
        /**
         * Producer Template.
         */
		 //获取endpoint
        MockEndpoint mock = getMockEndpoint("mock:output");
		//expected方法
        mock.expectedBodiesReceived(expected);
        String input="Hello";
		//使用producer创建消息
        template.sendBody("direct:sampleInput",input );
		//断言
        assertMockEndpointsSatisfied();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

更多关于MockEndpoint的内容: http://people.apache.org/~dkulp/camel/testing.html http://camel.apache.org/mock.html

例4:Spring XML DSL的路由测试

路由设计

把json数据中的email提取分解

<?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:camel="http://camel.apache.org/schema/spring"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

    <camel:camelContext id="jsonsplit">
        <camel:route>
            <camel:from uri="direct:start" />
            <camel:split streaming="true">
                <camel:jsonpath>$.[*].email</camel:jsonpath>
                    <camel:log message="${body}"></camel:log>
                    <camel:to uri="mock:result"></camel:to>
            </camel:split>
        </camel:route>
    </camel:camelContext>
</beans>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

测试用例

ProducerTemplate和MockEndpoint采用注解的方式注入,不用继承CamelTestSupport。 使用@RunWith(SpringJUnit4ClassRunner.class)声明为Spring测试用例


@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class CamelSplitTest {
    @EndpointInject(uri = "mock:result")
    private MockEndpoint mock;

    @Produce(uri = "direct:start")
    private ProducerTemplate template;

    @Test
    public void testSplit() throws Exception {
        mock.expectedBodiesReceived("ram@gmail.com","shyam23@gmail.com");
        mock.expectedMinimumMessageCount(2);
        String msg = "[  {\n" +
                "    \"name\": \"Ram\",\n" +
                "    \"email\": \"ram@gmail.com\",\n" +
                "    \"age\": 23,\n" +
                "    \"hobby\":[\n" +
                "      \"writing\",\n" +
                "      \"riding\",\n" +
                "      \"drawing\"\n" +
                "    ]\n" +
                "  },\n" +
                "  {\n" +
                "    \"name\": \"Shyam\",\n" +
                "    \"email\": \"shyam23@gmail.com\",\n" +
                "    \"age\": 28\n" +
                "  }]";
        template.sendBody(msg);
        mock.assertIsSatisfied();
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

更多关于CamelSpring测试的内容:http://camel.apache.org/spring-testing.html

例5:SpringBoot Camel测试---XML import方式集成Camel

@SpringBootApplication
@ImportResource({"classpath:camel-context.xml"})
public class CamelSplitJsonApplication {

    public static void main(String[] args) {
        SpringApplication.run(CamelSplitJsonApplication.class, args);
    }

}
1
2
3
4
5
6
7
8
9

路由设计

CamelSplitJsonApplicationTests-context.xml

    <camel:camelContext id="jsonAggregate">
        <camel:route>
            <camel:from uri="direct:start" />
            <camel:split streaming="true">
                <camel:jsonpath>$.[*].email</camel:jsonpath>
                    <camel:log message="${body}"></camel:log>
                    <camel:to uri="mock:result"></camel:to>
            </camel:split>
        </camel:route>
    </camel:camelContext>
1
2
3
4
5
6
7
8
9
10

测试用例

CamelSplitJsonApplicationTests

@RunWith(SpringRunner.class)
@SpringBootTest
public class CamelSplitJsonApplicationTests {

    @Produce(uri="direct:start")
    private ProducerTemplate template;

    @EndpointInject(uri="mock:result")
    private  MockEndpoint mockEndpoint;


    @Test
    public void testSplit() throws InterruptedException {
        mockEndpoint.expectedBodiesReceived("ram@gmail.com","shyam23@gmail.com");
        mockEndpoint.expectedMessageCount(2);
        String msg = "[ {\n" +
            "    \"name\": \"Ram\",\n" +
            "    \"email\": \"ram@gmail.com\",\n" +
            "    \"age\": 23,\n" +
            "    \"hobby\":[\n" +
            "      \"writing\",\n" +
            "      \"riding\",\n" +
            "      \"drawing\"\n" +
            "    ]\n" +
            "  },\n" +
            "  {\n" +
            "    \"name\": \"Shyam\",\n" +
            "    \"email\": \"shyam23@gmail.com\",\n" +
            "    \"age\": 28\n" +
            "  },]";
        template.sendBody(msg);
        mockEndpoint.assertIsSatisfied();
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

例5:SpringBoot Camel测试-RouteBuilder

路由设计

在路由类上使用component注解,Spring boot会自动配置,创建实例注入CamelContext

@Component
public class MyCamelRouter extends RouteBuilder{

    @Override
    public void configure() throws Exception {
        from("timer:hello?period={{timer.period}}").routeId("hello").routeGroup("hello-group")
            .transform().method("myBean", "saySomething")
            .filter(simple("${body} contains 'foo'"))
            .to("log:foo")
            .end()
            .to("stream:out");
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14

测试用例

  • CamelSpringBootRunner:将CamelSpringTestSupport的功能引入基于Spring Boot Test的测试用例的实现。 这种方法允许开发人员使用典型的测试开发Spring测试约定来实现基于Spring Boot的应用程序/路由的测试。
  • EnableRouteCoverage:启用保存路由测试覆盖统计,路由覆盖统计保存在target/camel-route-coverage目录。
  • MockEndpoints: 模拟端点
@RunWith(CamelSpringBootRunner.class)
@SpringBootTest(classes = CamelSplitJsonApplication.class,
    properties = "greeting = Hello foo")
@EnableRouteCoverage
@MockEndpoints("log:foo") // mock the log:foo endpoint => mock:log:foo which we then use in the testing
//@Ignore // enable me to run this test as well so we can cover testing the route completely
public class FooApplicationTest {

    @Autowired
    private CamelContext camelContext;

    @EndpointInject(uri = "mock:log:foo")
    private MockEndpoint mock;

    @Test
    public void shouldSayFoo() throws Exception {
        mock.expectedBodiesReceived("Hello foo");

        // we expect that one or more messages is automatic done by the Camel
        // route as it uses a timer to trigger
        NotifyBuilder notify = new NotifyBuilder(camelContext).whenDone(1).create();

        assertTrue(notify.matches(10, TimeUnit.SECONDS));

        mock.assertIsSatisfied();
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

例6:SpringBoot Camel测试-RouteBuilder-2

路由设计

@Component
public class AnimalRoute extends RouteBuilder {

    public static final String CAMEL_FILE_NAME = "CamelFileName";

    @Override
    public void configure() throws Exception {

        from("{{animalSource}}")
            .log("got message")
            .choice()
            .when(p -> p.getIn().getHeader(CAMEL_FILE_NAME).toString().contains("dog"))
            .log("found a dog!")
            .to("{{dogEndpoint}}")
            .when(p -> p.getIn().getHeader(CAMEL_FILE_NAME).toString().contains("cat"))
            .log("looks like a cat!")
            .to("{{catEndpoint}}");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

application.properties

animalSource=file://animals
dogEndpoint=file://dogs
catEndpoint=file://cats

1
2
3
4

application-test.properties

animalSource=direct:animalSource
dogEndpoint=mock:dogEndpoint
catEndpoint=mock:catEndpoint
1
2
3

测试用例

测试用例开发方法:

  • create the context,
  • load the correct properties for testing,
  • inject messages into the route and
  • verify the result messages.
  • @DirtiesContext annotation ensures that we always get a fresh Camel context for each test.
import junit.framework.TestCase;
import org.apache.camel.EndpointInject;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.spring.CamelSpringBootRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;

@RunWith(CamelSpringBootRunner.class)
@SpringBootTest(classes = AnimalRouteTest.class)
@ActiveProfiles("test")
@ComponentScan
public class AnimalRouteTest extends TestCase {

    public static final String NICE_DOG = "nice dog", NASTY_CAT="nasty cat", SUPERNASTY_CAT="super nasty cat";

    @EndpointInject(uri = "{{dogEndpoint}}")
    protected MockEndpoint dogEndpoint;

    @EndpointInject(uri = "{{catEndpoint}}")
    protected MockEndpoint catEndpoint;

    @EndpointInject(uri = "{{animalSource}}")
    protected ProducerTemplate animalSource;

    @Test
    @DirtiesContext
    public void testDog() throws Exception {

        animalSource.sendBodyAndHeader("test", AnimalRoute.CAMEL_FILE_NAME, NICE_DOG);


        dogEndpoint.message(0).predicate(m -> {
            String header = m.getIn().getHeader(AnimalRoute.CAMEL_FILE_NAME).toString();
            return NICE_DOG.equals(header);
        });
        dogEndpoint.expectedMessageCount(1);
        dogEndpoint.assertIsSatisfied();

        catEndpoint.expectedMessageCount(0);
        catEndpoint.assertIsSatisfied();
    }

    @Test
    @DirtiesContext
    public void testCat() throws Exception {


        animalSource.sendBodyAndHeader("test", AnimalRoute.CAMEL_FILE_NAME, NASTY_CAT);
        animalSource.sendBodyAndHeader("test", AnimalRoute.CAMEL_FILE_NAME, SUPERNASTY_CAT);


        catEndpoint.message(0).predicate(m -> {
            String header = m.getIn().getHeader(AnimalRoute.CAMEL_FILE_NAME).toString();
            return NASTY_CAT.equals(header);
        });

        catEndpoint.message(1).predicate(m -> {
            String header = m.getIn().getHeader(AnimalRoute.CAMEL_FILE_NAME).toString();
            return SUPERNASTY_CAT.equals(header);
        });

        catEndpoint.expectedMessageCount(2);

        dogEndpoint.expectedMessageCount(0);

        dogEndpoint.assertIsSatisfied();

        catEndpoint.assertIsSatisfied();



    }

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

更多内容阅读:

  • http://camel.apache.org/spring-boot.html
  • https://stackoverflow.com/questions/47796388/spring-boot-and-camel-testing-with-springboottest