gpt4 book ai didi

java - 如何使用模拟覆盖@Produces

转载 作者:行者123 更新时间:2023-12-02 04:30:26 26 4
gpt4 key购买 nike

我有一个类,它生成一个 ElasticSearch 客户端以与 @Inject 一起使用

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

我想在我的单元测试中使用如下内容来模拟这个客户端

@Produces
@Mock
private Client client;

这会导致 AmbigouslyResolutionException,因为同一个 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);
}
}

测试-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));
}
}

这可行,但不太可测试。您可能想使用模拟进行单元测试,没有 Activity 连接。我们可以重构它以使其更具可测试性。考虑这个替代实现:

@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 文件中激活此替代方案即可。

关于java - 如何使用模拟覆盖@Produces,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31551932/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com