2015-07-22 1 views
0

У меня есть класс, который производит клиент ElasticSearch для использоваться с @InjectКак переопределить @Produces с издеваться

@Produces 
@ApplicationScoped 
public Client createClient() { 
    return new TransportClient().addTransportAddress(new InetSocketTransportAddress(IP, 9300)); 
} 

Я хочу, чтобы дразнить этот клиент в моих модульных тестах с чем-то вроде следующего

@Produces 
@Mock 
private Client client; 

Это приводит к исключению AmbiguousResolutionException, поскольку для одного и того же компонента существует два поставщика.

Как присвоить приоритет только моему модульному классу только для модульных тестов?


Из комментариев ниже я внесла следующие изменения. Я поставил точку останова в альтернативе, но ее не ударили.

ElasticSearchProducer.java

@ApplicationScoped 
public class ElasticSearchProducer { 

    public static final String IP = "10.9.215.28"; 

    private Client client; 

    @PostConstruct 
    public void init() { 
     client = createClient(); 
    } 

    protected Client createClient() { 
     return new TransportClient().addTransportAddress(new InetSocketTransportAddress(IP, 9300)); 
    } 

    @Produces 
    @ApplicationScoped 
    public Client getClient() { 
     return client; 
    } 
} 

ElasticSearchProducerAlternative.java

@Alternative 
@ApplicationScoped 
public class ElasticSearchProducerAlternative extends ElasticSearchProducer { 

    @Override 
    public Client createClient() { 
     return Mockito.mock(Client.class); 
    } 
} 

тест-beans.xml

<?xml version="1.0" encoding="UTF-8"?> 
<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://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> 

    <alternatives> 
     <class>com.walmart.platform.pv.cdi.ElasticSearchProducerAlternative</class> 
    </alternatives> 

</beans> 

ArquillianTest.java

@RunWith(Arquillian.class) 
public abstract class ArquillianTest { 
    @Deployment(testable = true) 
    public static WebArchive createDeployment() { 


     WebArchive war = ShrinkWrap.create(WebArchive.class, "quintessence.war") 
       .addPackages(true, "com.w.platform"); 

     war.merge(ShrinkWrap.create(GenericArchive.class).as(ExplodedImporter.class) 
         .importDirectory("src/main/webapp").as(GenericArchive.class), 
       "/", Filters.includeAll()); 

     war.addAsManifestResource("etc/conf/test/import.sql"); 
     war.addAsManifestResource("test-persistence.xml", "persistence.xml"); 
     war.addAsWebInfResource("test-beans.xml", "beans.xml"); 
     war.addAsWebInfResource("test-resources.xml", "resources.xml"); 

     System.out.println(war.toString(true)); 
     return war; 
    } 
} 

В моем испытании альтернативный класс не используется

ответ

2

Необходимо помнить, что всегда следует писать тестируемый код. Предположим, что ваш класс написан так:

@ApplicationScoped 
public class ESClient { 
    @Produces 
    @ApplicationScoped 
    public Client createClient() { 
     return new TransportClient().addTransportAddress(new InetSocketTransportAddress(IP, 9300)); 
    } 
} 

Это работает, но не очень проверяемо. Вы можете использовать макет для модульных тестов, без активного подключения. Мы можем реорганизовать это, чтобы быть более проверяемым. Рассмотрим эту альтернативную реализацию:

@ApplicationScoped 
public class ESClient { 
    private Client client; 
    @PostConstruct 
    public void init() { 
     this.client = createClient(); 
    } 
    @Produces 
    @ApplicationScoped 
    public Client getClient() { 
     return this.client; 
    } 
    protected Client createClient() { 
     return new TransportClient().addTransportAddress(new InetSocketTransportAddress(IP, 9300)); 
    } 
} 

Да, это немного более подробно, но ваши проблемы лучше разделены. Вы можете предоставить альтернативную реализацию в тестах

@ApplicationScoped 
@Alternative 
public class MockESClient extends ESClient { 
    @Override 
    protected Client createClient() { 
     // return your mock here 
    } 
} 

Теперь вам просто нужно активировать эту альтернативу в файле beans.xml.

+0

Благодарим за отзыв, я попытался внести изменения и столкнулся с проблемой. Можете ли вы просмотреть изменения, которые я сделал выше. –

+0

Эта строка не выглядит корректной в вашем фрагменте, вы можете исправить это? 'WebArchive war = ShrinkWrap.create (WebArchive.class," test.war "). AddPackages (true," test); ' –

+0

Также вы можете уточнить, что такое время выполнения? Контейнер + версия? –