[英]How to override @Produces with a mock
我有一个类产生一个与@Inject一起使用的ElasticSearch客户端
@Produces
@ApplicationScoped
public Client createClient() {
return new TransportClient().addTransportAddress(new InetSocketTransportAddress(IP, 9300));
}
我想在单元测试中使用以下类似方法模拟此客户端
@Produces
@Mock
private Client client;
这将导致AmbiguousResolutionException,因为同一bean有两个提供程序。
如何仅将模拟生成的类优先用于单元测试?
从下面的评论中,我进行了以下更改。 我在替代方法中设置了一个断点,但没有受到打击。
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);
}
}
test-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;
}
}
在我的测试中,未使用替代类
您需要记住始终编写可测试的代码。 假设您的班级是这样写的
@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
文件中激活此替代方法即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.