春季骆驼测试使用多个上下文

时间:2016-02-18 16:33:15

标签: apache-camel

我使用Spring在不同的xml中有两个驼峰上下文(A和B)。当我只加载一个上下文我的junit工作,但当我尝试加载两个上下文时,Endpoint注入失败运行junit。

那么,有人有一个示例如何使用Spring camel使用多个上下文进行测试吗?

春季测试

public class BaseSpringTest extends CamelSpringTestSupport
{
    protected AbstractXmlApplicationContext createApplicationContext()
    {
        return new ClassPathXmlApplicationContext("camel-config.xml");
    }
} 

我的档案camel-config.xml

<beans>
 <context:annotation-config/>
 <import resource="classpath:camel-test-dao.xml" />
 <import resource="classpath:camel-contextA.xml"/>
 <import resource="classpath:camel-contextB.xml"/>
</beans>

我的背景:

<camelContext xmlns="camel.apache.org/schema/spring" id="contextA"> 
 ...
</camelContext>
<camelContext xmlns="camel.apache.org/schema/spring" id="contextB"> 
...
</camelContext>

我的单元测试,无法注入Endpoint

@EndpointInject(uri = "direct:myroute", context="contextB")
private Endpoint eFooTest;

堆栈跟踪:

org.apache.camel.spring.GenericBeansException: Error post processing bean: com.mycompany.test.FooTest; nested exception is java.lang.NullPointerException
  at org.apache.camel.spring.CamelBeanPostProcessor.postProcessBeforeInitialization(CamelBeanPostProcessor.java:154)
  at org.apache.camel.test.spring.CamelSpringTestSupport.postProcessTest(CamelSpringTestSupport.java:62)
  at org.apache.camel.test.junit4.CamelTestSupport.doSetUp(CamelTestSupport.java:319)
  at org.apache.camel.test.junit4.CamelTestSupport.setUp(CamelTestSupport.java:238)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
  at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
  at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
  at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
  at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
  at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
  at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
  at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.NullPointerException
  at org.apache.camel.impl.CamelPostProcessorHelper.matchContext(CamelPostProcessorHelper.java:84)
  at org.apache.camel.impl.DefaultCamelBeanPostProcessor$1.doWith(DefaultCamelBeanPostProcessor.java:181)
  at org.apache.camel.util.ReflectionHelper.doWithFields(ReflectionHelper.java:73)
  at org.apache.camel.impl.DefaultCamelBeanPostProcessor.injectFields(DefaultCamelBeanPostProcessor.java:168)
  at org.apache.camel.impl.DefaultCamelBeanPostProcessor.postProcessBeforeInitialization(DefaultCamelBeanPostProcessor.java:82)
  at org.apache.camel.spring.CamelBeanPostProcessor.postProcessBeforeInitialization(CamelBeanPostProcessor.java:148)
  ... 31 more

显然CamelBeanPostProcessor存在一个错误,当有一个上下文时,返回一个空值!

  

if(contexts!= null&amp;&amp; contexts.size()== 1){

@XmlTransient
private final DefaultCamelBeanPostProcessor delegate = new DefaultCamelBeanPostProcessor() {
    @Override
    public CamelContext getOrLookupCamelContext() {
        if (camelContext == null) {
            if (camelId != null) {
                LOG.trace("Looking up CamelContext by id: {} from Spring ApplicationContext: {}", camelId, applicationContext);
                camelContext = applicationContext.getBean(camelId, CamelContext.class);
            } else {
                // lookup by type and grab the single CamelContext if exists
                LOG.trace("Looking up CamelContext by type from Spring ApplicationContext: {}", applicationContext);
                Map<String, CamelContext> contexts = applicationContext.getBeansOfType(CamelContext.class);
                if (contexts != null && contexts.size() == 1) {
                    camelContext = contexts.values().iterator().next();
                }
            }
        }
        return camelContext;
    }

Camel 2.16.2 Spring 4.1.5 JDK 1.7 JDK 1.8

2 个答案:

答案 0 :(得分:0)

我一直在努力解决这个问题。最后,我设法了解了一个解决方法,它允许我使用生产中使用的原始路径xml文件,但结合到一个camel上下文中,以便能够将其用于测试。这样我就可以为bean端点注入模拟,并通过在模拟上声明来检查整个过程。

有两种不同的捆绑包。一个来自发票,另一个来自电子邮件。这些路线协调了这个过程。

首先,我将生产xml文件上的路由外部化。发票捆绑包的Spring上下文( invoicing-spring-context.xml )和路由( invoicing-routes.xml )文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    ...
    <camelContext id="invoicingCamelContext"
        xmlns="http://camel.apache.org/schema/spring">
        <routeContextRef ref="invoicingRoutes"/>
    </camelContext>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    <routeContext id="invoicingRoutes" xmlns="http://camel.apache.org/schema/spring">
        <route id="planner" autoStartup="true">
            <from uri="quartz://planner?cron=0+0+23+16+*+?" />
            <to uri="direct:invoicing" />
        </route>

        <route id="invoicing" autoStartup="true">
            <from uri="direct:invoicing?exchangePattern=InOut" />
            <to uri="bean:invoicer?method=generateInvoices" />
            <to uri="direct-vm:emailing" />
        </route>
    </routeContext>
</beans>

用于通过电子邮件发送捆绑包的Spring上下文( emailing-spring-context.xml )和路由( emailing-routes.xml ):

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    ...
    <camelContext id="emailingCamelContext"
        xmlns="http://camel.apache.org/schema/spring">
        <routeContextRef ref="emailingRoutes"/>
    </camelContext>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    <routeContext id="emailingRoutes" xmlns="http://camel.apache.org/schema/spring">
        <route id="emailing" autoStartup="true">
            <from uri="direct-vm:emailing" />
            <to uri="bean:emailer?method=createEmails" />
            <to uri="bean:emailer?method=sendEmails" />
        </route>
    </routeContext>
</beans>

然后出于测试目的,我创建了另一个弹簧上下文( complete-process-test-spring-context.xml ),它导入了两个路径文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    ...
    <camelContext id="completeProcessTestCamelContext"
        xmlns="http://camel.apache.org/schema/spring">      
        <routeContextRef ref="invoicingRoutes"/>
        <routeContextRef ref="emailingRoutes"/>
    </camelContext>
</beans>

测试类看起来像:

public class CompleteProcessTest extends CamelSpringTestSupport {
    @Test
    public void completeProcess() {
        ...

        invoicerMock.generateInvoices(EasyMock.isA(Exchange.class));
        emailerMock.createEmails(EasyMock.isA(Exchange.class));
        emailerMock.sendEmails(EasyMock.isA(Exchange.class));

        EasyMock.replay(invoicerMock);
        EasyMock.replay(emailerMock);

        this.template.requestBody(this.context.getEndpoint("direct://invoicing"), "");

        EasyMock.verify(invoicerMock);
        EasyMock.verify(emailerMock);
    }

    @Override
    protected AbstractApplicationContext createApplicationContext() {
        return new ClassPathXmlApplicationContext("classpath:/META-INF/spring/invoicing-routes.xml",
                "classpath:/META-INF/spring/emailing-routes.xml",
                "classpath:/META-INF/spring/complete-process-test-spring-context.xml");
    }

    ...
}

答案 1 :(得分:0)

感谢@ Jorge-c,但是使用routeContext,我们连续只有一个CamelContext。

要在单元测试中使用乘法上下文,请不要使用CamelSpringTestSupport,否则会出现错误。

public class BaseSpringTest extends CamelSpringTestSupport {...}

使用“@RunWith(SpringJUnit4ClassRunner.class)”

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/camel-my-root-spring-config.xml")
public class BaseSpringJUnit4 
{
  @EndpointInject(uri = "direct:myroute", context="contextB")
  private Endpoint eFooTest;
}

这个有效! 不要忘记在端点注释中加上explicitilly context =“contextB”

Camel 2.16.2 Spring 4.1.5 JDK 1.7 JDK 1.8