java - Mockito 监视被单元测试的对象

标签 java unit-testing junit mockito

监视正在接受单元测试的对象是否有代码味道?例如,假设我有一个 LineCounter 类,它的工作是简单地计算字符串中的行数。 --

class LineCounter {
    public int getNumLines(String string) {
        String metadata = getStringMetadata(string);

        // count lines in file
        return numLines;
    }

    /** Expensive operation */
    protected String getStringMetadata(String string) {
        // do stuff with string
    }
}

现在我想为此编写一个 JUnit 4 测试来测试 getNumLines 方法,同时模拟昂贵的 getStringMetadata 调用。我决定使用 Mockito 的 spy 机制让 getStringMetadata 返回一个虚拟值。

class LineCounterTests {
    @Test public void testGetNumLines() {
        LineCounter lineCounterSpy = Mockito.spy(new LineCounter());

        // Mock out expensive call to return dummy value.            
        Mockito.when(lineCounterSpy.getStringMetadata(Mockito.anyString()).thenReturn("foo");

        assertEquals(2, lineCounterSpy.getNumLines("hello\nworld");
    }
}

这样做合理吗?我觉得测试 Spy 对象而不是实际类很奇怪,但我真的想不出反对它的理由。

最佳答案

我将分两部分回答这个问题。首先,是的,模拟或监视被测类是代码味道。这并不意味着它不能正确完成,而是它存在风险,应尽可能避免。

WRT 你的具体例子,我会看到如何正确使用 spy ,但这将基于你在其他地方已经完全单元测试 getStringMetadata 的断言。这就引出了一个问题,如果您在其他地方对 getStringMetadata 进行了完整的单元测试,那么您必须知道如何测试它,因此为什么不在没有 spy 的情况下测试 getNumLines

综上所述,millhouse 提出了一个很好的观点,但无论哪种方式,您都必须在某处对昂贵的代码进行单元测试。他的建议对帮助隔离昂贵的代码并确保您只需测试/运行一次有很大帮助。

关于java - Mockito 监视被单元测试的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19261014/

相关文章:

java - 使用 JUnit 理论测试采用 String 参数的方法

java - 使用 Play! 进行 Web 开发框架

java - Java 字节码中存在多个静态 block 会发生什么情况?

java - 带有 CONCAT 的 NamedQuery 返回错误

unit-testing - 测试 TLV 协议(protocol)

java - 多次运行同一个 Gradle 任务

java - 如何在netbeans中组织不同的java源文件夹(用于测试)?

java - 如何将度、分、秒转换为十进制坐标

spring - 使用@WebMvcTest 时如何排除使用 Spring 的 AutoConfiguration 添加的类?

asp.net - 启动 ASP.NET 开发 Web 服务器 (Cassini) 作为单元测试设置的一部分?