diff --git a/needle/src/main/java/cucumber/runtime/java/needle/NeedleFactory.java b/needle/src/main/java/cucumber/runtime/java/needle/NeedleFactory.java index f695b646bc..eeda51f2b2 100644 --- a/needle/src/main/java/cucumber/runtime/java/needle/NeedleFactory.java +++ b/needle/src/main/java/cucumber/runtime/java/needle/NeedleFactory.java @@ -39,8 +39,21 @@ public T getInstance(final Class type) { @Override public void start() { logger.trace("start()"); - for (final Class stepDefinitionType : cachedStepsInstances.keySet()) { - cachedStepsInstances.put(stepDefinitionType, createStepsInstance(stepDefinitionType)); + try { + // First create all instances + for (final Class stepDefinitionType : cachedStepsInstances.keySet()) { + cachedStepsInstances.put(stepDefinitionType, createStepsInstance(stepDefinitionType)); + } + // Then collect injection providers from all instances + for (Object stepsInstance : cachedStepsInstances.values()) { + addInjectionProvider(collectInjectionProvidersFromStepsInstance.apply(stepsInstance)); + } + // Now init all instances, having the injection providers from all other instances available + for (Object stepsInstance : cachedStepsInstances.values()) { + initTestcase(stepsInstance); + } + } catch (final Exception e) { + throw new IllegalStateException(e); } } @@ -78,16 +91,9 @@ private T nullSafeGetInstance(final Class type) { return (T) instance; } - private T createStepsInstance(final Class type) { + private T createStepsInstance(final Class type) throws Exception { logger.trace("createInstance(): " + type.getCanonicalName()); - try { - final T stepsInstance = createInstanceByDefaultConstructor.apply(type); - addInjectionProvider(collectInjectionProvidersFromStepsInstance.apply(stepsInstance)); - initTestcase(stepsInstance); - return stepsInstance; - } catch (final Exception e) { - throw new IllegalStateException(e); - } + return createInstanceByDefaultConstructor.apply(type); } static InjectionProvider[] setUpInjectionProviders(final String resourceName) { diff --git a/needle/src/test/java/cucumber/runtime/java/needle/test/AtmWithdrawalSteps.java b/needle/src/test/java/cucumber/runtime/java/needle/test/AtmWithdrawalSteps.java index d5b9e31e5a..9a4250fb66 100755 --- a/needle/src/test/java/cucumber/runtime/java/needle/test/AtmWithdrawalSteps.java +++ b/needle/src/test/java/cucumber/runtime/java/needle/test/AtmWithdrawalSteps.java @@ -1,24 +1,28 @@ package cucumber.runtime.java.needle.test; -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.when; - -import javax.inject.Inject; - -import org.hamcrest.core.Is; - +import cucumber.api.java.Before; import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; import cucumber.api.java.en.When; +import cucumber.api.needle.InjectionProviderInstancesSupplier; import cucumber.api.needle.NeedleInjectionProvider; +import cucumber.runtime.java.needle.injection.DefaultInstanceInjectionProvider; import cucumber.runtime.java.needle.test.atm.AtmService; import cucumber.runtime.java.needle.test.atm.AtmServiceBean; import cucumber.runtime.java.needle.test.atm.BicGetter; import cucumber.runtime.java.needle.test.injectionprovider.ValueInjectionProvider; import de.akquinet.jbosscc.needle.annotation.ObjectUnderTest; import de.akquinet.jbosscc.needle.injection.InjectionProvider; +import org.hamcrest.core.Is; + +import javax.inject.Inject; + +import java.util.Collections; +import java.util.Set; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.*; +import static org.mockito.Mockito.when; public class AtmWithdrawalSteps { @@ -31,12 +35,23 @@ public class AtmWithdrawalSteps { @Inject private BicGetter bicGetter; + @Inject + private MoreSteps moreSteps; + /* * Provider instance will be added dynamically. */ @NeedleInjectionProvider private final InjectionProvider valueProvider = new ValueInjectionProvider(VALUE); + @NeedleInjectionProvider + private final InjectionProviderInstancesSupplier thisInjectionProviderSupplier = new InjectionProviderInstancesSupplier() { + @Override + public Set> get() { + return Collections.>singleton(new DefaultInstanceInjectionProvider(AtmWithdrawalSteps.this)); + } + }; + /* * This is what we test */ @@ -65,4 +80,12 @@ public void I_have_EUR_remaining(final int remaining) throws Throwable { assertThat(atmService.getAmount(), Is.is(remaining)); } + @Before + public void checkInjectionWorked() { + assertTrue("Got a mock injected instead of the real instance.", moreSteps.isThisReallyYouOrJustAMock()); + } + + public boolean isThisReallyYouOrJustAMock() { + return true; + } } diff --git a/needle/src/test/java/cucumber/runtime/java/needle/test/MoreSteps.java b/needle/src/test/java/cucumber/runtime/java/needle/test/MoreSteps.java new file mode 100644 index 0000000000..6155bf1ebf --- /dev/null +++ b/needle/src/test/java/cucumber/runtime/java/needle/test/MoreSteps.java @@ -0,0 +1,38 @@ +package cucumber.runtime.java.needle.test; + +import cucumber.api.java.Before; +import cucumber.api.java.en.Given; +import cucumber.api.needle.NeedleInjectionProvider; +import cucumber.runtime.java.needle.injection.DefaultInstanceInjectionProvider; +import de.akquinet.jbosscc.needle.injection.InjectionProvider; + +import javax.inject.Inject; + +import static org.junit.Assert.assertTrue; + +/** + * Just here to show that injection providers from this class also work in other classes. + * + * @author Lars Bilger + */ +public class MoreSteps { + + @NeedleInjectionProvider + private InjectionProvider thisInjectionProvider = new DefaultInstanceInjectionProvider(this); + + @Inject + private AtmWithdrawalSteps atmWithdrawalSteps; + + @Before + public void checkInjectionWorked() { + assertTrue("Got a mock injected instead of the real instance.", atmWithdrawalSteps.isThisReallyYouOrJustAMock()); + } + + @Given("^i call a step that i don't really need$") + public void this_step_is_here_only_to_have_the_class_instantiated() { + } + + public boolean isThisReallyYouOrJustAMock() { + return true; + } +}