如何使用Apache Camel多次单元测试相同的路由?

huangapple go评论49阅读模式
英文:

How do i unit test the same route multiple times using Apache Camel

问题

我正在使用CamelTestSupport,目前有两个单元测试针对一个路由。这两个单元测试的目的是测试是否抛出异常,我使用AdviceWith来替换并抛出异常。

问题出在文档中建议只在路由上应用Advice一次,因为这会导致第二个单元测试无法匹配路由。

我该怎么办才能在每个单元测试后重置路由呢?

英文:

I am using CamelTestSupport and currently have 2 unit test for 1 routes.
Both unit test is to test if exception is thrown, I used AdviceWith to replace and throw Exception.

The issue arises as written in the documentation it is recommended to only Advice the route once as it will cause the 2nd unit test to not match the route.

What can i do to reset the route after each unit test?

答案1

得分: 0

The issue arises as written in the documentation it is recommended to only Advice the route once as it will cause the 2nd unit test to not match the route.

问题出在文档中建议只对路由进行一次建议,否则会导致第二个单元测试无法匹配路由。

Where does it read like this in the documentation?

文档中哪里提到了这一点?

Using AdviceWith to modify the same route in different unit tests seems to work just fine. You should also be able to modify the same route in the same unit tests twice or more for as long the modifications do not conflict with each other.

使用AdviceWith在不同的单元测试中修改相同的路由似乎完全可以工作。您还应该能够在相同的单元测试中多次修改相同的路由,只要这些修改不互相冲突。

I would however avoid or at least be very careful when using AdviceWith in methods annotated with @BeforeAll or @BeforeEach as these changes will be applied for each test. Same goes for many overridable CamelTestSupport methods.

但是,我建议避免或至少在使用AdviceWith时要非常小心在使用@BeforeAll@BeforeEach注解的方法中,因为这些更改将应用于每个测试。对于许多可重写的CamelTestSupport方法也是如此。

Example

示例:

package com.example;

import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.AdviceWith;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;

public class MultiAdviceWithExampleTests extends CamelTestSupport {

    class ExceptionA extends Exception {}
    class ExceptionB extends Exception {}

    @Test
    public void exampleThrowsExceptionA() throws Exception{

        AdviceWith.adviceWith(context, "example", builder -> {

            builder.weaveByToUri("direct:replaceMe")
                .replace()
                .log("Throwing Exception A")
                .throwException(new ExceptionA());
        });

        MockEndpoint exceptionAMockEndpoint = getMockEndpoint("mock:exceptionA");
        MockEndpoint exceptionBMockEndpoint = getMockEndpoint("mock:exceptionB");
        exceptionAMockEndpoint.expectedMessageCount(1);
        exceptionBMockEndpoint.expectedMessageCount(0);

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

        exceptionBMockEndpoint.assertIsSatisfied();
        exceptionAMockEndpoint.assertIsSatisfied();
    }

    @Test
    public void exampleThrowsExceptionB() throws Exception{

        AdviceWith.adviceWith(context, "example", builder -> {

            builder.weaveByToUri("direct:replaceMe")
                .replace()
                .log("Throwing Exception B")
                .throwException(new ExceptionB());
        });

        MockEndpoint exceptionAMockEndpoint = getMockEndpoint("mock:exceptionA");
        MockEndpoint exceptionBMockEndpoint = getMockEndpoint("mock:exceptionB");
        exceptionAMockEndpoint.expectedMessageCount(0);
        exceptionBMockEndpoint.expectedMessageCount(1);
        
        startCamelContext();
        template.sendBody("direct:example", null);

        exceptionAMockEndpoint.assertIsSatisfied();
        exceptionBMockEndpoint.assertIsSatisfied();
    }

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

            @Override
            public void configure() throws Exception {
                
                from("direct:example")
                    .id("example")
                    .onException(ExceptionA.class)
                        .log("Caught exception A")
                        .to("mock:exceptionA")
                        .handled(true)
                    .end()
                    .onException(ExceptionB.class)
                        .log("Caught exception A")
                        .to("mock:exceptionB")
                        .handled(true)
                    .end()
                    .to("direct:replaceMe")
                ;
                
                from("direct:replaceMe")
                    .routeId("replaceMe")
                    .log("should not be displayed.");
            }
            
        };
    }

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

自从覆盖isUseAdviceWith方法以返回true强制每个测试手动启动camel上下文,我假设CamelTestsSupport要么为每个测试创建单独的上下文和路由,要么至少在测试之间重置路由和模拟端点的状态。

Both unit tests are to test if an exception is thrown. I used AdviceWith to replace and throw an exception.

这两个单元测试的目的都是测试是否抛出异常。我使用AdviceWith来替换并抛出异常。

If you're using JUnit's assertThrows, it might not work as you expect with Apache Camel, as Camel will likely throw one of its own exceptions instead. To get the original exception, you can use template.send and get the resulting exception from the resulting exchange through .getException().getClass().

如果您正在使用JUnit的assertThrows,那么在Apache Camel中它可能不会按您的预期工作,因为Camel可能会抛出其自己的异常。要获取原始异常,您可以使用template.send,并通过.getException().getClass()从生成的交换中获取结果异常。

// Remove the onException blocks from the route with this 
// or getException() will return null
Exchange result = template.send("direct:example", new DefaultExchange(context));
assertEquals(ExceptionB.class, result.getException().getClass());

从路由中删除onException块,否则getException()将返回null。

英文:

> The issue arises as written in the documentation it is recommended to only Advice the route once as it will cause the 2nd unit test to not match the route.

Where does it read like this in the documentation?

Using AdviceWith to modify same route in different unit tests seems to work just fine. You should also be able to modify the same route in the same unit tests twice or more for as long the modifications do not conflict with each other.

I would however avoid or at least be very careful when using AdviceWith in methods annotated with @BeforeAll or @BeforeEach as these changes will be applied for each test. Same goes for many overridable CamelTestSupport methods.

Example

package com.example;

import org.apache.camel.RoutesBuilder;
import org.apache.camel.builder.AdviceWith;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.test.junit5.CamelTestSupport;
import org.junit.jupiter.api.Test;

public class MultiAdviceWithExampleTests extends CamelTestSupport {

    class ExceptionA extends Exception {}
    class ExceptionB extends Exception {}

    @Test
    public void exampleThrowsExceptionA() throws Exception{

        AdviceWith.adviceWith(context, "example", builder -> {

            builder.weaveByToUri("direct:replaceMe")
                .replace()
                .log("Throwing Exception A")
                .throwException(new ExceptionA());
        });


        MockEndpoint exceptionAMockEndpoint = getMockEndpoint("mock:exceptionA");
        MockEndpoint exceptionBMockEndpoint = getMockEndpoint("mock:exceptionB");
        exceptionAMockEndpoint.expectedMessageCount(1);
        exceptionBMockEndpoint.expectedMessageCount(0);

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

        exceptionBMockEndpoint.assertIsSatisfied();
        exceptionAMockEndpoint.assertIsSatisfied();
    }

    @Test
    public void exampleThrowsExceptionB() throws Exception{

        AdviceWith.adviceWith(context, "example", builder -> {

            builder.weaveByToUri("direct:replaceMe")
                .replace()
                .log("Throwing Exception B")
                .throwException(new ExceptionB());
        });

        MockEndpoint exceptionAMockEndpoint = getMockEndpoint("mock:exceptionA");
        MockEndpoint exceptionBMockEndpoint = getMockEndpoint("mock:exceptionB");
        exceptionAMockEndpoint.expectedMessageCount(0);
        exceptionBMockEndpoint.expectedMessageCount(1);
        
        startCamelContext();
        template.sendBody("direct:example", null);

        exceptionAMockEndpoint.assertIsSatisfied();
        exceptionBMockEndpoint.assertIsSatisfied();
    }

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

            @Override
            public void configure() throws Exception {
                
                from("direct:example")
                    .id("example")
                    .onException(ExceptionA.class)
                        .log("Caught exception A")
                        .to("mock:exceptionA")
                        .handled(true)
                    .end()
                    .onException(ExceptionB.class)
                        .log("Caught exception A")
                        .to("mock:exceptionB")
                        .handled(true)
                    .end()
                    .to("direct:replaceMe")
                ;
                
                from("direct:replaceMe")
                    .routeId("replaceMe")
                    .log("should not be displayed.");
            }
            
        };
    }

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

Since overriding the isUseAdviceWith method to return true forces one to start camel context manually for each tests I am assuming that CamelTestsSupport either creates separate context and routes for each tests or at least resets the routes and mock endpoints to their original states between tests.

> Both unit test is to test if exception is thrown, I used AdviceWith to replace and throw Exception.

If you're using JUnits assertThrows it might not work as you expect with Apache Camel as Camel will likely throw one of it's own Exceptions instead. To get the original Exception you can use template.send and get the resulting exception from the resulting exchange through .getException().getClass().

// Remove the onException blocks from route with this 
// or getException() will return null
Exchange result = template.send("direct:example", new DefaultExchange(context));
assertEquals(ExceptionB.class, result.getException().getClass()); 

huangapple
  • 本文由 发表于 2023年3月3日 18:15:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75625757.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定