cucumber-javapicocontainer

How to configure PicoContainer in Cucumber?


I would like to manually configure my picocontainer to have configured instances of configuration objects for my cucumber build. I.E, providing configuration objects a-la @ConfigurationProperties in Spring.

However, it is not clear how to do so. The website gives a lot of documentation on how to manipulate a container, but no context surrounding those examples. I am using a Cucumber maven build, using the cucumber-picocontainer dependency.

Ideally PicoContainer would be able to pick up dependencies from a main yaml/ config file like Spring, but if I can manually enter them into the running container, that works too.

For clarity, I know I can do:

@RunWith(Cucumber.class)
public class RunWithCucumberTest{

    public PicoContainer getContainer(){
        MutablePicoContainer pico = new DefaultPicoContainer();
        //do the config, inject onjects, etc

        return pico;
    }
}

But this does not mean that the instance returned by this is actually used to inject my properties.

In conclusion, I am looking for a way to use pico container to do one of the following:


Solution

  • Those features are not available. Picocontainer is a very simple dependency injection framework and Cucumbers usage of it is even simpler. To use it effectively try not to use it as if you are constructing an application graph. Rather use it to construct the API that you use to test your application.

    Typically you'd end up wrapping objects that can't instantiate themselves and those wrappers everywhere. This is not very flexible but generally this flexibility isn't needed. Your step definitions + support classes should manipulate the application under test.

    If that doesn't work for you can also use cucumber-guice or cucumber-spring which use Guice and Spring for dependency injection respectively.

    You can also roll your own implementation of the PicoFactory, its a trivial amount of code and if its the only ObjectFactory implementation it will be used automatically. Otherwise you can use the object-factory property/option.

    public class Configuration {
    
        private final Properties someProperties = new Properties();
    
        public Configuration() throws IOException {
            someProperties.load(Properties.class.getResourceAsStream("some.properties"));
        }
    
        public String entryPoint() {
            return someProperties.getProperty("example.entry-point", "localhost:7070/entry");
        }
    
    }
    
    public class StepDefinitions {
    
        private final Configuration configuration;
        private Application application;
    
        public StepDefinitions(Configuration configuration) {
            this.configuration = configuration;
        }
    
        @Given("a thing is done")
        public void aThingIsDone(){
            String entryPoint = configuration.entryPoint();
            this.application = //... create application with entry point
        }
    
    }