Search code examples
javaunit-testingopenstack-swiftjclouds

Transient mode for unit tests with jclouds and Openstack Swift doesn't work


I just migrated to jclouds 2.0.0 (it was suppose to some of the problems with not repeatable operations and it did). Here are the dependencies

    <dependency>
        <groupId>org.apache.jclouds.driver</groupId>
        <artifactId>jclouds-slf4j</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.jclouds.api</groupId>
        <artifactId>openstack-keystone</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.jclouds.api</groupId>
        <artifactId>openstack-swift</artifactId>
        <version>2.0.0</version>
    </dependency>

I want to have unit tests for my code. But when I use transient as a provider:

SwiftApi swiftApi = ContextBuilder.newBuilder("transient")
                .endpoint(endpoint)
                .credentials(user, password)
                .modules(modules)
                .overrides(overrides)
                .buildApi(SwiftApi.class);

I get this exception:

com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for org.jclouds.openstack.swift.v1.SwiftApi was bound.
  while locating org.jclouds.openstack.swift.v1.SwiftApi

1 error

    at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)
    at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1009)
    at org.jclouds.ContextBuilder.buildApi(ContextBuilder.java:651)
    at org.jclouds.ContextBuilder.buildApi(ContextBuilder.java:643)
    at eu.europeana.cloud.service.mcs.persistent.swift.SimpleSwiftConnectionProvider.openConnections(SimpleSwiftConnectionProvider.java:91)
    at eu.europeana.cloud.service.mcs.persistent.swift.SimpleSwiftConnectionProvider.<init>(SimpleSwiftConnectionProvider.java:67)
    at eu.europeana.cloud.service.mcs.persistent.swift.SimpleSwiftConnectionProviderTest.getContainer(SimpleSwiftConnectionProviderTest.java:24)
    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:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    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 com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

The same code run with openstack-swift as provider (and correct credentials and endpoint) works just fine. Passing any other string as newBuilder function parameter cause:

java.util.NoSuchElementException: key [wrongstring] not in the list of providers or apis: {apis=[openstack-keystone, openstack-swift, transient]}
    at org.jclouds.ContextBuilder.newBuilder(ContextBuilder.java:175)

which made me think that transient should be supported. But how to make it work?


Solution

  • You can't create a SwiftApi view of a transient blobstore; instead you must use the portable BlobStore view:

    String provider = ...;  // openstack-swift or transient
    BlobStoreContext context = ContextBuilder.newBuilder(provider)
                .endpoint(endpoint)
                .credentials(user, password)
                .buildApi(BlobStoreContext.class);
    BlobStore blobStore = context.getBlobStore();
    // interact with blobStore, e.g., get, put
    ...
    context.close();