| [[BlueprintTesting-BlueprintTesting]] |
| Blueprint Testing |
| ~~~~~~~~~~~~~~~~~ |
| |
| *Available as of Camel 2.10* |
| |
| [Info] |
| ==== |
| |
| |
| *camel-test-blueprint* does only support testing one CamelContext. So if |
| you have 2 or more CamelContexts in your blueprint XML files, then first |
| found CamelContext is used during testing. |
| |
| ==== |
| |
| link:testing.html[Testing] is a crucial part of any development or |
| integration work. Camel supports the definition of |
| link:using-osgi-blueprint-with-camel.html[Blueprint routes], but given |
| Blueprint is an OSGi specific technology, writing unit tests is quite |
| difficult. This library leverages |
| http://code.google.com/p/pojosr/[PojoSR] which provides a service |
| registry without using a fully compliant OSGi container. This allows |
| defining real unit tests (as opposed to integration tests using |
| http://team.ops4j.org/wiki/display/paxexam/Pax+Exam[Pax Exam]. Please |
| make sure all test jars in you class path are OSGi bundle. |
| |
| Also notice the use of *`getBlueprintDescriptor`* to specify the |
| location of the OSGi Blueprint XML file. + |
| If you have multiple OSGi Blueprint XML files, then you can specify |
| them with a comma-separated list in the *`getBlueprintDescriptor`* |
| method. |
| |
| Here's the |
| http://svn.apache.org/viewvc/camel/trunk/components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/camelContext.xml?view=markup[Blueprint |
| XML file]: |
| |
| In order to define blueprint tests, add the following dependency in your |
| pom: |
| |
| [source,xml] |
| ----------------------------------------------- |
| <dependency> |
| <groupId>org.apache.camel</groupId> |
| <artifactId>camel-test-blueprint</artifactId> |
| <version>2.10</version> |
| <scope>test</scope> |
| </dependency> |
| ----------------------------------------------- |
| |
| [[BlueprintTesting-Classpathscanning]] |
| Classpath scanning |
| ^^^^^^^^^^^^^^^^^^ |
| |
| By default PojoSR test container scans the test classpath for all the |
| OSGi bundles available there. All the bundles with Blueprint descriptor |
| files will be automatically started by the test container. If you would |
| like to prevent particular bundles from being started by the test |
| container, override the `getBundleFilter` method, just as demonstrated |
| on the snippet below. |
| |
| [source,java] |
| -------------------------------------------------------------------------------- |
| @Override |
| protected String getBundleFilter() { |
| // I don't want test container to scan and load Logback bundle during the test |
| return "(!(Bundle-SymbolicName=ch.qos.logback.core))"; |
| } |
| -------------------------------------------------------------------------------- |
| |
| Keep in mind that not specifying the Blueprint descriptor in the |
| *`getBlueprintDescriptor`* method will not prevent the test container |
| from loading given descriptor. Bundle filter method is the proper way of |
| filtering out bundles you don't want to start during the test. |
| |
| [[BlueprintTesting-SettingtimeoutwhengettingCamelContext]] |
| Setting timeout when getting CamelContext |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| *Available as of Camel 2.13.0/2.12.1/2.11.2* |
| |
| `CamelBlueprintTestSupport` waits 30 sec for Camel Context to be ready |
| by default, now you can override this value in two ways: |
| |
| * Globally, by setting |
| `org.apache.camel.test.blueprint.camelContextCreationTimeout` system |
| property. |
| * Locally for each test, by overriding _getCamelContextCreationTimeout_ |
| method. |
| |
| [[BlueprintTesting-Addingservicesonstartup]] |
| Adding services on startup |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| |
| *Available as of Camel 2.11.2/2.12.0* |
| |
| When using `camel-test-blueprint` you may do unit tests which requires |
| using shared services which is not available during unit testing, but |
| only in the real OSGi container, for example a shared `DataSource`. |
| |
| To make it easier to register services on startup, such as a standalone |
| `DataSource` or any other service, you can override the method |
| `addServicesOnStartup` when your unit test class extends |
| `CamelBlueprintTestSupport`. |
| |
| In the example below we register a service |
| `org.apache.camel.test.blueprint.MyService` using the name `myService` |
| having a property `beer=Carlsberg`, as shown below: |
| |
| [source,java] |
| --------------------------------------------------------------------------------------------------- |
| @Override |
| protected void addServicesOnStartup(Map<String, KeyValueHolder<Object, Dictionary>> services) { |
| services.put("myService", asService(myService, "beer", "Carlsberg")); |
| } |
| --------------------------------------------------------------------------------------------------- |
| |
| The asService is a builder method that makes it easy to register a |
| service with a single property. If you need more properties you can use |
| the `asService` method that takes a `Dictionary` as argument. And if you |
| do not need any properties, then just pass in `null`, eg: |
| |
| [source,java] |
| ------------------------------------------------------ |
| services.put("myService", asService(myService, null)); |
| ------------------------------------------------------ |
| |
| This allows us to use the service by calling a method on it from a Camel |
| link:bean.html[Bean] component in a route as shown: |
| |
| [source,xml] |
| -------------------------------- |
| <route> |
| <from uri="direct:start"/> |
| <to uri="bean:myService"/> |
| <to uri="mock:result"/> |
| </route> |
| -------------------------------- |
| |
| Notice the bean endpoint uses the service name `myService` which was the |
| name we registered the service as. You can also use the fully qualified |
| class name instead, which is more common with OSGi. |
| |
| [source,java] |
| --------------------------------------------------------------------------------------------------- |
| @Override |
| protected void addServicesOnStartup(Map<String, KeyValueHolder<Object, Dictionary>> services) { |
| services.put(MyService.class.getName(), asService(myService, "beer", "Carlsberg")); |
| } |
| --------------------------------------------------------------------------------------------------- |
| |
| And in the route we use the FQN name: |
| |
| [source,xml] |
| ---------------------------------------------------------------- |
| <route> |
| <from uri="direct:start"/> |
| <to uri="bean:org.apache.camel.test.blueprint.MyService"/> |
| <to uri="mock:result"/> |
| </route> |
| ---------------------------------------------------------------- |
| |
| |
| |
| From *Camel 2.16.0*, an additional `addServicesOnStartup` method is |
| available to be overridden making it ideal for when needing to specify |
| multiple services with the same interface. |
| |
| [source,java] |
| ------------------------------------------------------------------------------------------------------------------ |
| @Override |
| protected void addServicesOnStartup(List<KeyValueHolder<String, KeyValueHolder<Object, Dictionary>>> services) { |
| Dictionary<String, String> dict1 = new Hashtable<String, String>(); |
| dict1.put("osgi.jndi.service.name", "jdbc/db1"); |
| |
| Dictionary<String, String> dict2 = new Hashtable<String, String>(); |
| dict2.put("osgi.jndi.service.name", "jdbc/db2"); |
| |
| services.add(asKeyValueService(javax.sql.DataSource.class.getName(), mockService1, dict1)); |
| services.add(asKeyValueService(javax.sql.DataSource.class.getName(), mockService2, dict2)); |
| } |
| ------------------------------------------------------------------------------------------------------------------ |
| |
| The `asKeyValueService` builder method can be used to construct the |
| necessary parameters to create the service. The method takes in the name |
| of the registered service, the object, and and a `Dictionary` as |
| arguments. |