【问题标题】:How to override @Produces with a mock如何用模拟覆盖@Produces
【发布时间】:2015-07-22 00:32:52
【问题描述】:

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

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

我想在我的单元测试中模拟这个客户端,如下所示

@Produces
@Mock
private Client client;

这会导致 AmbiguousResolutionException,因为同一个 bean 有两个提供者。

我如何确定我的模拟生成类仅用于单元测试的优先级?


从下面的 cmets 中,我进行了以下更改。我在替代方案中设置了一个断点,但它没有被击中。

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

在我的测试中没有使用替代类

【问题讨论】:

    标签: java unit-testing mockito cdi java-ee-7


    【解决方案1】:

    您需要记住始终编写可测试的代码。假设你的类是这样写的

    @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 文件中激活此选项即可。

    【讨论】:

    • 感谢您的回复,我尝试更改并遇到问题。能否请您查看我在上面所做的修改。
    • 这条线在你的 sn-p 中看起来不正确,你能解决它吗? WebArchive war = ShrinkWrap.create(WebArchive.class, "test.war").addPackages(true, "test);
    • 另外,你能澄清一下你的运行时是什么吗?容器+版本?
    • 我更新了那行代码,我试图隐藏一些可能被视为敏感信息的内容。容器是 Tomee 1.7。感谢您的帮助!
    • 那么不要包括com.wmt ;-) 你能把邮件放在tomee 开发者列表上吗?这闻起来像是 OWB 或 TomEE 部署机制的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    • 2021-04-09
    • 1970-01-01
    • 2017-02-08
    • 2022-01-27
    • 2013-07-25
    相关资源
    最近更新 更多