Lets assume that I have sequencer and the following Beans. Sequencer is responsible for taking the next value from a database sequence. OracleSequencer is used in the production mode, TestSequencer during JUnit-Tests.
public interface Sequencer{
long getNextValue();
}
@Named("OracleSequencer")
public class OracleSequencer implements Sequencer[
...
}
@Named("TestSequencer")
public class TestSequencer implements Sequencer[
...
}
And this is how I want to use it:
@Named
public class BusinessBean{
@Inject
private Sequencer sequencer;
}
My problem is: When I run the app in the production mode I want to inject OracleSequencer in BusinessBean, when I run JUnit-Test I want to inject TestSequencer. Is it possible with JSR-330 (@Inject, @Named) ?
I found 2 dirty solutions:
at the begining of a test, Sequencer can be replaced in the bean, which is taken from Spring-ApplicationContext. It is possible when prototype is appropriate and TestSequencer doesnt have any other dependencies:
BusinessBean bean = springContext.getBean(..); bean.setSequencer(new TestSequencer());
We can annotate OracleSequencer with @ProductionScope and TestSequencer with @TestScope and configure Spring that he scans appropiate annotations in the appropriate mode.
Do you have maybe any other idea how to solve this problem?
Spring 3.1.
One solution would be to use Spring Profiles introduced with Spring 3.1, essentially define a profile named "prod" and "test", let your OracleSequencer
be created in prod
profile and TestSequencer
in test
profile.
For your test, activate the test
profile alone, and your prod activate the prod
profile.
Here is one reference to Profiles - http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/
Another solution like you suggested will be to override your sequencer
bean in test with the TestSequencer
, either by specifying a bean with the exact same name as your prod sequencer or specifying it in a new application context which is imported in test mode.