首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >静态工厂方法和模拟

静态工厂方法和模拟
EN

Stack Overflow用户
提问于 2015-12-02 00:26:00
回答 3查看 6.6K关注 0票数 6

如何使用静态工厂方法和mocking进行协调?

许多人只会说:不要使用静态工厂方法,而要使用DI。

嗯,有时候你不能避免使用静态工厂方法。考虑以下应该熟悉的用例:

假设您有一个名为Option的类,就像在scala中一样。如果您想对所有缺少的值重用相同的实例,则无法避免使用静态工厂方法。

一旦你使用new Option(null)创建了一个新的option对象,你就不能一遍又一遍地返回相同的对象。

类似的用例是Integer.valueOf(),它将对小于128的值重用整数对象。不使用静态工厂方法是不可能的。

另一个优点是工厂方法比new关键字更具描述性。

那么,你们如何处理必须使用静态工厂方法,同时又想使用继承和mock呢?

谢谢。

EN

回答 3

Stack Overflow用户

发布于 2015-12-02 00:35:55

既然这是一个理论问题,我就给出一个理论上的答案。工厂范例是另一种理论的构建点:注入。如果您创建的对象是在需要时注入的,那么您只需注入您的模拟对象即可完成所有测试。有很多好的书/网页可以帮助你开始使用它。

票数 2
EN

Stack Overflow用户

发布于 2015-12-02 00:36:23

使用PowerMock可以模拟静态方法。考虑他们的Wiki page中的以下示例

代码语言:javascript
复制
@Test
public void testRegisterService() throws Exception {
    long expectedId = 42;

    // We create a new instance of test class under test as usually.
    ServiceRegistartor tested = new ServiceRegistartor();

    // This is the way to tell PowerMock to mock all static methods of a
    // given class
    mockStatic(IdGenerator.class);

    /*
     * The static method call to IdGenerator.generateNewId() expectation.
     * This is why we need PowerMock.
     */
    expect(IdGenerator.generateNewId()).andReturn(expectedId);

    // Note how we replay the class, not the instance!
    replay(IdGenerator.class);

    long actualId = tested.registerService(new Object());

    // Note how we verify the class, not the instance!
    verify(IdGenerator.class);

    // Assert that the ID is correct
    assertEquals(expectedId, actualId);
}

甚至可以只模拟一个特定的方法,而使用partial mocking保持其他方法不变。

票数 2
EN

Stack Overflow用户

发布于 2015-12-02 00:41:14

我的第一个选择是避免模拟任何东西,所以有没有静态工厂方法都没有区别。

也就是说,如果我真的想或需要嘲笑他们,我就会这么做。例如,假设您正在测试一个基于JSF的web应用程序,并且您想要模拟javax.faces.context.FacesContext对象。我将使用JMockit库(碰巧是我开发的)在测试中编写以下代码:

代码语言:javascript
复制
@Test
public void exampleTest(@Mocked final FacesContext ctx) {
    // Call the code under test, which will at some point
    // call FacesContext.getCurrentInstance(), then add an
    // error message for display in the web page.

    new Verifications() {{
        FacesMessage msg;
        ctx.addMessage(null, msg = withCapture());

        assertEquals("The expected error message.", msg.getSummary());
        assertNotNull(msg.getDetail());
    }};
}

在本例中,Faces.getCurrentInstance()是静态工厂方法,一旦类被模拟,它将自动返回一个模拟的FacesContext实例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34025131

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档