Introduction

Dependency Injection has become an integral part of modern software design. We discuss here the different ways in which JBehave supports dependency injection.

Steps class-level injection

Steps classes often use external dependencies to interface to the system whose behaviour is being verified.

Using PicoContainer

Steps can be instantiated via PicoContainer using the PicoStepsFactory (the extension module jbehave-pico needs to be added to the classpath):

public class PicoTraderStory extends TraderStory {

    public PicoTraderStory(Class storyClass) {
        super(storyClass);
    }

    @Override
    protected CandidateSteps[] createSteps(StepsConfiguration configuration) {
        PicoContainer parent = createPicoContainer();
        return new PicoStepsFactory(configuration, parent).createCandidateSteps();
    }

    private PicoContainer createPicoContainer() { 
        // users can also use any other way to create a PicoContainer, e.g. via a script language        
        MutablePicoContainer parent = new DefaultPicoContainer(new Caching().wrap(new ConstructorInjection()));
        parent.as(Characteristics.USE_NAMES).addComponent(TradingService.class);
        parent.as(Characteristics.USE_NAMES).addComponent(TraderSteps.class);
        parent.as(Characteristics.USE_NAMES).addComponent(BeforeAfterSteps.class);
        return parent;
    }
    
}

Using Spring

Steps can be instantiated via Spring using the SpringStepsFactory (the extension module jbehave-spring needs to be added to the classpath):

public class SpringTraderStory extends TraderStory {

    public SpringTraderStory(Class storyClass) {
        super(storyClass);
    }

    @Override
    protected CandidateSteps[] createSteps(StepsConfiguration configuration) {
        ListableBeanFactory parent = createBeanFactory();
        return new SpringStepsFactory(configuration, parent).createCandidateSteps();
    }

    private ListableBeanFactory createBeanFactory() {
        return (ListableBeanFactory) new ClassPathXmlApplicationContext(
                new String[] { "org/jbehave/examples/trader/spring/steps.xml" });
    }

}

Using Guice

Steps can be instantiated via Using Guice using the GuiceStepsFactory (the extension module jbehave-guice needs to be added to the classpath):

public class GuiceTraderStory extends TraderStory {

    public GuiceTraderStory(Class storyClass) {
        super(storyClass);
    }

    @Override
    protected CandidateSteps[] createSteps(StepsConfiguration configuration) {
        Injector parent = createInjector();
        return new GuiceStepsFactory(configuration, parent).createCandidateSteps();
    }

    private Injector createInjector() {
        Injector parent = Guice.createInjector(new AbstractModule() {
            @Override
            protected void configure() {
              bind(TradingService.class).in(Scopes.SINGLETON);
              bind(GuiceTraderSteps.class).in(Scopes.SINGLETON);
              bind(BeforeAfterSteps.class).in(Scopes.SINGLETON);
            }
          });
        return parent;
    }
    
}
where the GuiceTraderSteps is appropriately Guice-annotated:
public class GuiceTraderSteps extends TraderSteps {

    @Inject
    public GuiceTraderSteps(TradingService service) {
        super(service);
    }

}