Сварка с использованием альтернативного производителя из src/test/META-INF/beans.xml

Я пытаюсь использовать Weld SE 2.3.0.Final, чтобы поменять альтернативную реализацию внедренной зависимости во время тестирования путем предоставления другого beans.xml в src/test/resources/META-INF

Кажется, всегда используется основная версия beans.xml хотя и я не уверен почему.

Прежде всего, здесь вспомогательные классы

Engine.java

public interface Engine
{
    void start();
    void stop();
}

DefaultEngine.java

@Vetoed
public class DefaultEngine implements Engine
{

    public void start()
    {
        System.out.println("Cough cough vrummmmm");
    }

    public void stop()
    {
        System.out.println("Phhhut clank");
    }

}

Car.java

public class Car
{
    @Inject
    private Engine engine;

    public void startCar()
    {
        engine.start();
    }

    public void stopCar()
    {
        engine.stop();
    }

}

EngineProducer.java

public class EngineProducer
{

    @Produces
    public Engine getEngine()
    {
        return new DefaultEngine();
    }

}

App.java

public class App 
{
    @Inject
    private Car car;

    public void main(@Observes ContainerInitialized event)
    {
        car.startCar();
        car.stopCar();
    }
}

И производственная версия beans.xml в src/main/resources/META-INF

<beans xmlns="http://java.sun.com/xml/ns/javaee" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/beans_1_0.xsd">
</beans>

Приведенный выше код при запуске из App.java должен напечатать (и это делает)

Cough cough vrummmmm
Phhhut clank

Теперь из тестового кода я хочу использовать SportsEngine реализация. Итак, у меня есть следующее

SportsEngine.java

@Vetoed
public class SportsEngine implements Engine
{

    public void start()
    {
        System.out.println("Vrummm vrummm vrummmm!");
    }

    public void stop()
    {
        System.out.println("Prrrrrr clunk");
    }

}

TestEngineProducer.java

@Alternative
public class TestEngineProducer
{

    @Produces
    public Engine getEngine()
    {
        return new SportsEngine();
    }

}

AppTest.java

@RunWith(WeldJUnit4Runner.class)
public class AppTest
{

    @Inject
    private Car car;

    @Test
    public void testCar()
    {
        car.startCar();
        car.stopCar();
    }

}

WeldJUnit4Runner.java

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;
    }
}

И тестовая версия beans.xml в src/test/resources/META-INF

<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
      http://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/beans_1_0.xsd">
    <alternatives>
        <class>com.test.testing.TestEngineProducer</class>
    </alternatives>
</beans>

Когда тестовый метод запущен, он должен напечатать

Vrummm vrummm vrummmm!
Prrrrrr clunk

Но вместо этого, кажется, использовать EngineProducer вместо TestEngineProducer и печатает вывод дважды

Cough cough vrummmmm
Phhhut clank
Cough cough vrummmmm
Phhhut clank

Почему он не использует test beans.xml?

Если я поставлю <alternatives> раздел из test beans.xml и поместите его в основной файл beans.xml, тогда он заработает, но я не хочу менять файл beans.xml в main/resources/META-INF при тестировании

1 ответ

Решение

Кажется, ошибка Weld Se. Он использует только версию beans.xml в каталоге src/main/resources/META-INF.

Решением является использование beans.xml в CDI-SE src/main/resources/META-INF/beans.xml для тестирования, и вам может понадобиться добавить в beans.xml.

У вас может быть другой производственный файл beans.xml и при экспорте кода в пакет развертывания (jar, war, ear). Не забудьте заменить тестируемый beans.xml на ваш производственный beans.xml.

Если вы разрабатываете веб-приложение. Вы можете создать свой производственный beans.xml в разделе WEB-INF. Существует 2 версии beans.xml, но WAS использует только WEB-INF/beans.xml.

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <scan>
        <exclude name="org.jboss.weld.**" />
        <exclude name="com.your_package.EngineProducer" />
    </scan>
    <alternatives>
        <class>com.test.testing.TestEngineProducer</class>
    </alternatives>
</beans>
Другие вопросы по тегам