模拟一个类的任何对象

3

我该如何模拟一个类的任意对象。

我的目标是让任何文件对象在调用exists()方法时返回true

例如:

Mockito.mock(File.class)
//return true for any object of File that calls exist()
File file = new File("thisDoesntExist");
assertEquals(true, file.exists());

如何实现这个?

这是被测试的方法(简化版)

@Override
public void load(InputArchive archive, int idx)
{
    archive.beginNode("Files", idx);

    File file = new File(archive.load("Path"));
    if(file.exists())
    {
         //if it gets here it'll pass the test
    }
}

我认为以上方法可以解决我的问题,但如果有更好/另一种解决方法,我会告诉你我为什么要这样做:

我之所以想这样做是因为我正在读取一个XML文件,该文件将基于<file>标记创建一个文件对象,然后测试此fileObjectCreatedFromXML是否存在,如果存在,则执行一些其他必要的操作。


@Makoto 不是的,这个文件是由XML创建的,但我可以更改XML的内容,这样会更容易吗? - Aequitas
你能分享一下被测试的方法吗?信息这么少,很难给出建议。但是,除非你可以更改创建文件的代码,以便例如注入一个工厂来创建文件(并且可以在你的测试中模拟返回一个File,它总是从exists返回true),否则没有太多可以做的。 - Mick Mnemonic
@MickMnemonic 我已经添加了这个方法。 - Aequitas
是的,大致就是这样。通常情况下,在测试方法内部创建使用new关键字创建的对象是无法进行模拟的,你必须提供一些方式将模拟对象注入到该方法中。其中一种方式是让你的被测类使用一个小的辅助类(例如FileFactory),并通过构造函数注入该类,以便创建文件。 - Mick Mnemonic
你实际上想在这里测试什么?由于被测试类中的 load 方法具有 void 返回类型,你真正能够测试的只是该方法可能产生的副作用。如果你想测试 InputArchive.load() 是否从正确的路径加载,那么你应该为该类编写一个单独的测试。 - Mick Mnemonic
显示剩余3条评论
1个回答

2

即使您在类中创建了File对象并且没有任何方法可以注入或引用它,仍然可以模拟您的File对象。几周前我遇到了这个问题,而PowerMock可以帮助您。

您需要使用PowerMockRunner注释您的测试类来运行。请参考以下示例:

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyClassThatWillBeTested.class)
public class MyUnitTest{
    private File mockedFile = mock(File.class);

    @Before
    public void setUp() throws Exception {
        PowerMockito.whenNew(File.class).withAnyArguments().thenReturn(mockedFile);
    }
}

@Test
public void myTestMethod(){
    //test your method here...
}

如果您只创建一个文件对象,这应该可以很好地为您工作。 现在,您可以操纵您的模拟对象,以返回您想要的内容。
when(mockedFile.exists()).thenReturn(true);

+1 因为它回答了问题,但不幸的是对我没有帮助,因为我不能使用 PowerMock,使用它会导致测试运行得太慢。 - Aequitas
难道不能只针对当前类使用PowerMock吗?一个单元测试类的影响不应该是明显的。 - Flowryn
是的,但如果它在一个测试类中使用,其他人也会开始使用它,然后很快它就会被广泛使用,单元测试开始需要花费几分钟来运行。 - Aequitas
直到现在我从未听说/遇到过这样的情况。无论如何,您可以尝试使用反射,或者更好的方法是将该字段声明为具有包可见性的类成员,以便您可以在单元测试中进行操作。还可以查看@VisibleForTesting注释。根据我的经验,有时为了测试目的,降低可见性可能更好一些。 - Flowryn
PS:如果回答了问题,我宁愿将其标记为已解决(因为这是Stackoverflow的目的),也许其他人需要这个答案,并且很容易找到它。关于您的用例,您可以发布一个新问题,在其中提到性能问题事实。 - Flowryn
这就是点赞的作用,如果有帮助到我,我会接受它。 - Aequitas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接