【问题标题】:Using JMockit, how do I mock a static factory method to return a Fake?使用 JMockit,我如何模拟静态工厂方法以返回 Fake?
【发布时间】:2017-04-03 16:16:22
【问题描述】:

使用 JMockit MockUp API,我如何模拟静态工厂方法以返回 Fake?

我的问题与how do i mock the a static method that provides an instance of the class being mocked with JMockit? 类似,但我的合作者的工厂方法在我的测试环境中引发了异常(这是正确的)。因此,我需要模拟工厂以消除有问题的操作。带有工厂方法的类是抽象的,只有一个包私有的构造函数。

也就是说,给定以下协作者,我如何模拟 collaboratorFactory() 方法以使其返回假的协作者? (协作者是我无法控制的第三方代码。)

public abstract class Collaborator {
    public static Collaborator collaboratorFactory() {
        //... some operations that throw in test env ...
        return new CollaboratorImpl();
    }

    Collaborator() { }

    public int methodToMock() {
        return 5;
    }
}

我的测试课是这样的:

public class ClassUnderTest {
    public int getValue() {
        return Collaborator.collaboratorFactory().methodToMock();
    }
}

我想用一个假的 Collaborator 测试“ClassUnderTest”,比如说,从“methodToMock()”返回一些已知值我已经这样定义了我的测试类:

public class TestClassUnderTest {

    static class MockCollaborator extends MockUp<Collaborator> {
        @Mock public int methodToMock() {
            return 124;
        }
    }

    @Test
    public void test1() throws Exception {
        new MockCollaborator();
        ClassUnderTest t1 = new ClassUnderTest();
        assertEquals(124, t1.getValue());
    }

}

当 Collaborator.collaboratorFactory() 在我的测试环境中引发异常时,此测试失败。我真正想做的是将 collaboratoryFactory() 存根,这样它只会返回假的 Collaborator。可能类似于以下内容:

    static class MockCollaborator extends MockUp<Collaborator> {
        @Mock public Collaborator collaboratorFactory() {
            // ... I don't know what to return here ...
        }
    }

在 collaboratorFactory() 模拟方法的主体(上图)中,我尝试返回 this.getMockInstance(),但它返回 null,因为要模拟的实际方法是静态的。

FWIW,我已经能够使用 Expectations API 来测试我需要测试的内容,但我觉得这也应该可以使用 MockUp API。

感谢任何帮助或建议。

【问题讨论】:

  • 你试过return new Collaborator()吗?或者,假设构造函数是private,通过反射实例化它?无论如何,正确的解决方案是有一个@Mocked Collaborator
  • 感谢@Rogério,我已经编辑了问题以表明 Collaborator 实际上是一个抽象类,所以我不能return new Collaborator() 或通过反射实例化。当我写这个问题时,这是我逃避的实际代码的一个微妙之处。我确实想出了一个解决方案,我将作为答案发布。
  • Collaborator 声明为abstract 是没有意义的,因为它只有private 构造函数(因此阻止了任何子类),并且因为这(只有私有构造函数)就足够了防止客户端代码实例化类。
  • 你是对的。构造函数是包私有的,而不是私有的。 collaboratorFactory() 返回子类的一个实例(由库定义,并且在同一个包中)。我更新了问题以更好地反映现实生活场景。

标签: java unit-testing jmockit


【解决方案1】:

因为 Collaborator 是抽象的,所以我必须使用两个 MockUps,一个用于 Collaborator,一个用于 CollaboratorImpl。抽象类中的工厂方法通过getMockedInstance()返回一个假实现类的实例:

static class MockCollaboratorImpl extends MockUp<CollaboratorImpl> {
    @Mock public void $init() {};
    @Mock public void $clinit() {};
    @Mock public int methodToMock() {
        return 124;
    }
}

static class MockCollaborator extends MockUp<Collaborator> {
    @Mock public Collaborator collaboratorFactory() {
        return new MockCollaboratorImpl().getMockInstance();
    }
}

【讨论】:

    猜你喜欢
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    相关资源
    最近更新 更多