I am trying to use Weld SE 2.3.0.Final to swap an alternative implementation of an injected dependency during testing by supplying a different beans.xml in src/test/resources/META-INF
It always seems to use the main version of beans.xml though and I'm not sure why.
First of all here are the supporting classes
{code:title=Engine.java|borderStyle=solid} public interface Engine { void start(); void stop(); } {code}
{code:title=DefaultEngine.java|borderStyle=solid} @Vetoed public class DefaultEngine implements Engine {
public void start() { System.out.println("Cough cough vrummmmm"); }
public void stop() { System.out.println("Phhhut clank"); }
} {code}
{code:title=Car.java|borderStyle=solid} public class Car { @Inject private Engine engine;
public void startCar() { engine.start(); }
public void stopCar() { engine.stop(); }
} {code}
{code:title=EngineProducer.java|borderStyle=solid} public class EngineProducer {
@Produces public Engine getEngine() { return new DefaultEngine(); }
} {code} {code:title=App.java|borderStyle=solid} public class App { @Inject private Car car;
public void main(@Observes ContainerInitialized event) { car.startCar(); car.stopCar(); } } {code}
And the production version of beans.xml in src/main/resources/META-INF
{code:xml} <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" version="1.1" bean-discovery-mode="all"> </beans> {code}
The above code when run from App.java should print (and it does)
Cough cough vrummmmm Phhhut clank
Now from the test code I want to use the SportsEngine implementation. So I have the following
{code:title=SportsEngine.java|borderStyle=solid} @Vetoed public class SportsEngine implements Engine {
public void start() { System.out.println("Vrummm vrummm vrummmm!"); }
public void stop() { System.out.println("Prrrrrr clunk"); }
} {code}
{code:title=TestEngineProducer.java|borderStyle=solid} @Alternative public class TestEngineProducer {
@Produces public Engine getEngine() { return new SportsEngine(); }
} {code}
{code:title=AppTest.java|borderStyle=solid} @RunWith(WeldJUnit4Runner.class) public class AppTest {
@Inject private Car car;
@Test public void testCar() { car.startCar(); car.stopCar(); }
} {code}
{code:title=WeldJUnit4Runner.java|borderStyle=solid} public class WeldJUnit4Runner extends BlockJUnit4ClassRunner {
/** The test class to run. */ private final Class<?> mKlass; /** Weld infrastructure. */ private final Weld weld; /** The container itself. */ private final WeldContainer container;
/** * Runs the class passed as a parameter within the container. * * @param klass * to run * @throws InitializationError * if anything goes wrong. */ public WeldJUnit4Runner(final Class<Object> klass) throws InitializationError { super(klass); this.mKlass = klass; this.weld = new Weld(); this.container = weld.initialize(); }
@Override protected Object createTest() throws Exception { final Object test = container.instance().select(mKlass).get(); return test; } } {code}
And the test version of beans.xml in src/test/resources/META-INF
{code:xml} <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" version="1.1" bean-discovery-mode="all"> <alternatives> <class>com.test.testing.TestEngineProducer</class> </alternatives> </beans> {code}
When the test method is run it should print
Vrummm vrummm vrummmm! Prrrrrr clunk
But instead it seems to use the EngineProducer instead of the TestEngineProducer and prints the output twice
Cough cough vrummmmm Phhhut clank Cough cough vrummmmm Phhhut clank
Why is it not using the test beans.xml?
If I put the <alternatives> section from test beans.xml and put it in the main beans.xml then it works, but I don't want to swap the beans.xml in main/resources/META-INF when I'm testing
|