This is an automated email from the ASF dual-hosted git repository. aldettinger pushed a commit to branch CAMEL-13342-JUNIT5-EXPLORATORY in repository https://gitbox.apache.org/repos/asf/camel.git
commit e3c347205aa5e98116ed65f4121120b617bba4fa Author: aldettinger <aldettin...@gmail.com> AuthorDate: Wed Jun 5 16:50:19 2019 +0200 CAMEL-13342: Setup SimpleMockTest with junit extension and parameter resolver --- components/camel-test/pom.xml | 12 +++- .../org/apache/camel/test/junit5/CamelTest.java | 4 ++ .../camel/test/junit5/CamelTestExtension.java | 82 ++++++++++++++++++++++ .../test/junit5/CamelTestParameterResolver.java | 39 ++++++++++ .../apache/camel/test/junit5/SimpleMockTest.java | 53 ++++++++++++++ 5 files changed, 189 insertions(+), 1 deletion(-) diff --git a/components/camel-test/pom.xml b/components/camel-test/pom.xml index c3485f4..ebe758a 100644 --- a/components/camel-test/pom.xml +++ b/components/camel-test/pom.xml @@ -57,7 +57,17 @@ <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> - <version>5.5.0-M1</version> + <version>5.4.2</version> + </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter-engine</artifactId> + <version>5.4.2</version> + </dependency> + <dependency> + <groupId>org.junit.vintage</groupId> + <artifactId>junit-vintage-engine</artifactId> + <version>5.4.2</version> </dependency> <dependency> diff --git a/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTest.java b/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTest.java index 05ed250..2732d2a 100644 --- a/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTest.java +++ b/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTest.java @@ -21,8 +21,12 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.junit.jupiter.api.extension.ExtendWith; + @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) +@ExtendWith(CamelTestExtension.class) +@ExtendWith(CamelTestParameterResolver.class) public @interface CamelTest { } diff --git a/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTestExtension.java b/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTestExtension.java new file mode 100644 index 0000000..3e26d80 --- /dev/null +++ b/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTestExtension.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.test.junit5; + +import java.lang.reflect.Method; +import java.util.Optional; + +import org.apache.camel.ConsumerTemplate; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.impl.DefaultCamelContext; +import org.apache.camel.impl.engine.DefaultCamelBeanPostProcessor; +import org.apache.camel.model.ModelCamelContext; +import org.junit.jupiter.api.extension.AfterEachCallback; +import org.junit.jupiter.api.extension.BeforeEachCallback; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.platform.commons.util.ReflectionUtils; + +public class CamelTestExtension implements BeforeEachCallback, AfterEachCallback { + + private ModelCamelContext context; + private ProducerTemplate producerTemplate; + private ConsumerTemplate consumerTemplate; + + @Override + public void afterEach(ExtensionContext eCtx) throws Exception { + if (producerTemplate != null) { + producerTemplate.stop(); + } + if (consumerTemplate != null) { + consumerTemplate.stop(); + } + if (context != null) { + context.stop(); + } + } + + @Override + public void beforeEach(ExtensionContext eCtx) throws Exception { + context = new DefaultCamelContext(); + + Optional<Method> method = ReflectionUtils.findMethod(eCtx.getTestClass().get(), "createRouteBuilder"); + + Object ret = ReflectionUtils.invokeMethod(method.get(), eCtx.getTestInstance().get()); + if (ret instanceof RoutesBuilder) { + ((RoutesBuilder)ret).addRoutesToCamelContext(context); + } + producerTemplate = context.createProducerTemplate(); + consumerTemplate = context.createConsumerTemplate(); + + DefaultCamelBeanPostProcessor processor = new DefaultCamelBeanPostProcessor(context); + processor.postProcessBeforeInitialization(this, getClass().getName()); + processor.postProcessAfterInitialization(this, getClass().getName()); + + context.start(); + producerTemplate.start(); + consumerTemplate.start(); + + // @TODO: Do we really use a namespace with key + // CamelTestParameterResolver.class + // We may reuse those values in test also + eCtx.getStore(Namespace.create(CamelTestParameterResolver.class)).put(ModelCamelContext.class, context); + eCtx.getStore(Namespace.create(CamelTestParameterResolver.class)).put(ProducerTemplate.class, producerTemplate); + eCtx.getStore(Namespace.create(CamelTestParameterResolver.class)).put(ConsumerTemplate.class, consumerTemplate); + } + +} diff --git a/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTestParameterResolver.java b/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTestParameterResolver.java new file mode 100644 index 0000000..ce58940 --- /dev/null +++ b/components/camel-test/src/main/java/org/apache/camel/test/junit5/CamelTestParameterResolver.java @@ -0,0 +1,39 @@ +package org.apache.camel.test.junit5; + +import org.apache.camel.ConsumerTemplate; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.model.ModelCamelContext; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.jupiter.api.extension.ParameterResolver; + +// @TODO: Is it really the same treatment for all types ? +// @TODO: Can't we get more than one object of type ProducerTemplate ? like threadTemplate ? +public class CamelTestParameterResolver implements ParameterResolver { + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + // @TODO: clearer is better + Class<?> paramClass = parameterContext.getParameter().getType(); + return paramClass == ProducerTemplate.class || paramClass == ConsumerTemplate.class || paramClass == ModelCamelContext.class; + } + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { + final Class<?> paramClass = parameterContext.getParameter().getType(); + if (paramClass == ProducerTemplate.class) { + // @TODO: Is it safe to use class as store keys + return extensionContext.getStore(Namespace.create(CamelTestParameterResolver.class)).get(ProducerTemplate.class); + } else if (paramClass == ConsumerTemplate.class) { + // @TODO: Is it safe to use class as store keys + return extensionContext.getStore(Namespace.create(CamelTestParameterResolver.class)).get(ConsumerTemplate.class); + } else if (paramClass == ModelCamelContext.class) { + // @TODO: Is it safe to use class as store keys + return extensionContext.getStore(Namespace.create(CamelTestParameterResolver.class)).get(ModelCamelContext.class); + } + final String msgFormat = "Test %s can't receive a parameter of type %s. Expecting Context, ProduderTempate or ConsumerTemplate}"; + throw new ParameterResolutionException(String.format(msgFormat, extensionContext.getDisplayName(), paramClass.getName())); + } +} diff --git a/components/camel-test/src/test/java/org/apache/camel/test/junit5/SimpleMockTest.java b/components/camel-test/src/test/java/org/apache/camel/test/junit5/SimpleMockTest.java new file mode 100644 index 0000000..33987ac --- /dev/null +++ b/components/camel-test/src/test/java/org/apache/camel/test/junit5/SimpleMockTest.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.test.junit5; + +import org.apache.camel.ProducerTemplate; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.model.ModelCamelContext; +import org.junit.jupiter.api.Test; + +@CamelTest +public class SimpleMockTest { + + @Test + public void testMock(ProducerTemplate template, ModelCamelContext ctx) throws Exception { + MockEndpoint mockResult = ctx.getEndpoint("mock:result", MockEndpoint.class); + mockResult.expectedBodiesReceived("Hello World"); + template.sendBody("direct:start", "Hello World"); + MockEndpoint.assertIsSatisfied(ctx); + } + + /* Same test is shorter with junit4 + @Test + public void testMock() throws Exception { + getMockEndpoint("mock:result").expectedBodiesReceived("Hello World"); + template.sendBody("direct:start", "Hello World"); + assertMockEndpointsSatisfied(); + }*/ + + protected RoutesBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start").to("mock:result"); + } + }; + } +}