使用事务测试Apache Camel路由

时间:2018-10-24 14:58:47

标签: transactions apache-camel

我在政策中使用了transacted()的骆驼路线。在我的JUnit测试期间,我不想测试路由中的事务行为。我正在尝试使用以下方法将其删除:

weaveByType(TransactedDefinition.class).remove();

但错误地指出:

java.lang.IllegalArgumentException: There are no outputs which matches: TransactedDefinition in the route.

有什么办法可以从骆驼路线中删除交易 以更好的方式?

1 个答案:

答案 0 :(得分:1)

我更喜欢在JUnit测试中模拟TransactionManagerSpringTransactionPolicy,而不是从路由中删除事务行为。

您可以使用我的实用程序类:

import org.apache.camel.impl.JndiRegistry;
import org.apache.camel.spring.spi.SpringTransactionPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.*;
import org.springframework.transaction.support.*;

import javax.naming.NamingException;
import javax.transaction.TransactionManager;
import java.lang.reflect.Field;

public class TransactionalMock {
    private static final Logger LOG = LoggerFactory.getLogger(TransactionalMock.class);

    public static void register(JndiRegistry registry) throws NamingException {
        AbstractPlatformTransactionManager transactionManager = new AbstractPlatformTransactionManager() {
            @Override
            protected Object doGetTransaction() throws TransactionException {
                return null;
            }
            @Override
            protected void doBegin(Object o, TransactionDefinition transactionDefinition) throws TransactionException {
                LOG.info("doBegin {}, {}", o, transactionDefinition);
            }
            @Override
            protected void doCommit(DefaultTransactionStatus defaultTransactionStatus) throws TransactionException {
                LOG.info("doCommit {}", defaultTransactionStatus);
            }
            @Override
            protected void doRollback(DefaultTransactionStatus defaultTransactionStatus) throws TransactionException {
                LOG.info("doRollback {}", defaultTransactionStatus);
            }
        };
        //transactionManager.setNestedTransactionAllowed(true);

        unbindType(registry, TransactionManager.class);
        replaceBean(registry, "transactionManager", transactionManager);

        for (Field propagation: TransactionDefinition.class.getFields()){
            if (propagation.getName().startsWith(DefaultTransactionDefinition.PREFIX_PROPAGATION)){
                SpringTransactionPolicy springTransactionPolicy = new SpringTransactionPolicy();
                springTransactionPolicy.setTransactionManager(transactionManager);
                springTransactionPolicy.setPropagationBehaviorName(propagation.getName());
                replaceBean(registry, propagation.getName(), springTransactionPolicy);
            }
        }
    }

    private static void replaceBean(JndiRegistry registry, String name, Object bean) throws NamingException {
        if (registry.lookupByName(name) != null){
            registry.getContext().unbind(name);
        }
        registry.bind(name, bean);
    }
    private static void unbindType(JndiRegistry registry, Class<?> type) throws NamingException {
        for (String name: registry.lookupByType(type).keySet()){
            registry.getContext().unbind(name);
        }
    }
}

TransactionalMock#register的示例用法:

public class TransactionalMockTest extends CamelTestSupport {

    @Override
    protected RoutesBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from("direct:transacted")
                        .transacted()
                        .to("mock:transacted");
                from("direct:required")
                        .transacted("PROPAGATION_REQUIRED")
                        .to("mock:required");
                from("direct:requiresNew")
                        .transacted("PROPAGATION_REQUIRES_NEW")
                        .to("mock:requiresNew");
                    }
        };
    }

    @Override
    protected JndiRegistry createRegistry() throws Exception {
        JndiRegistry registry = super.createRegistry();
        TransactionalMock.register(registry);
        return registry;
    }

    @Test
    public void testTransacted() throws Exception{
        MockEndpoint mockEndpoint = getMockEndpoint("mock:transacted");
        template.sendBody("direct:transacted","");
        mockEndpoint.setExpectedCount(1);
        mockEndpoint.assertIsSatisfied();
    }
    @Test
    public void testTransactedRequired() throws Exception{
        MockEndpoint mockEndpoint = getMockEndpoint("mock:required");
        template.sendBody("direct:required","");
        mockEndpoint.setExpectedCount(1);
        mockEndpoint.assertIsSatisfied();
    }
    @Test
    public void testTransactedRequiresNew() throws Exception{
        MockEndpoint mockEndpoint = getMockEndpoint("mock:requiresNew");
        template.sendBody("direct:requiresNew","");
        mockEndpoint.setExpectedCount(1);
        mockEndpoint.assertIsSatisfied();
    }
}