I'm using Cucumber
with Guice
as DI.
I've encountered following problem:
I've got one step i.e.
class MyStep() {
@Inject
private MyService myService;
@Given("Some acction happen")
public void sthHappen() {
myService.doSth();
}
}
And I've got this class to run it as JUnit
test
@RunWith(Cucumber.class)
@CucumberOptions(...)
public class MyTest {
}
There is a
class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(MyService.class).to(MyFirstService.class);
}
}
which is used by my MyInjectorSource
I define cucumber.properties where I define guice.injector-source=MyInjectorSource;
There is also a feature file with scenario.
Everything is working for now.
And no i would like to run MyStep step with other MyService implementation (of course I don't wont to duplicate code of MyStep) I define a new feature file with new scenarios, and new Test class
@RunWith(Cucumber.class)
@CucumberOptions(...)
public class MyOtherTest {
}
And now I've tried to create another InjectorSource
but I was not able to configure it.
Solution which I've found is using custom Junit4 runner inheriting from original Cucumber runner and changing its
createRuntime
method.Latest cucumber-guice 1.2.5 uses few stages to create injector and unfortunately it uses global variable
cucumber.runtime.Env.INSTANCE
. This variable is populated fromcucumber.properties
andSystem.getProperties
.Flow is:
cucumber.runtime.java.JavaBackend
)ObjectFactory
(in my setup it is cucumber.runtime.java.guice.impl.GuiceFactory)Env.INSTANCE
, it will create customInjectorSource
or default injectorIdeally cucumber should pass its 'RuntimeOptions` created at start to backend and InjectorSource but unfortunately it doesn't and uses global variable. It is not easy create patch like this one so my solution simplifies this approach and directly create InjectorSource in custom runner by reading new annotation.
I needed to copy GuiceFactory because it doesn't exposes normal constructor (!)