java - 如何对调用私有(private)方法链的方法进行单元测试?

标签 java unit-testing junit jmock

    public void publicMethod() {
        privateMethod1();
        privateMethod2();
        privateMethod3();
        privateMethod4();
    }

    private void privateMethod4() {
        anotherPrivateMethodOrServiceCall();
        // ....
    }

    private void privateMethod3() {
        anotherPrivateMethodOrServiceCall();
        // ....
    }

    private void privateMethod2() {
        anotherPrivateMethodOrServiceCall();
        // ....
    }

    private void privateMethod1() {
        anotherPrivateMethodOrServiceCall();
        // ....
    }

如果不将其设置为默认值,则无法单独测试私有(private)方法(这有点难看)。 如果我从公共(public)方法测试它,它总是会导致 super 大的 mock 和断言。维护这么大的测试用例是一件痛苦的事情。还有其他好的方法或做法来解决这个问题吗?谢谢。

// long list of service mocking

@Test
public void testPublicMethod() {
    context.checking(new Expectations() {{
    // super long list of result mocking
    }});
    // ...
    // super long list of assertions
    assertEquals(....);
}

最佳答案

我对 Java 或特别是 Java 中的单元测试知之甚少,所以我在这里的观察是相对于一般单元测试而言的纯粹的一般性

  • 看来您的类(class)在内部做了太多事情。如果有一个原因导致您需要进行 4 个私有(private)方法调用作为单个公共(public)调用的结果,那么您很可能处于违反 SRP 的区域(并不是说这条规则不是不可违反的,但它是设计的一个很好的指标气味)

  • 现在我们没有太多关于您的“外部”类正在做什么的上下文,但考虑到所提供的信息,也许您可​​以考虑重构这 4 个私有(private)方法中每一个所完成的工作 成 4 个独立的,您可以将它们作为主类的依赖项提供;然后,您更改测试方法以进行多个较小的测试,每个测试仅检查是否调用了特定的依赖项

例如,您的方法名称可能如下所示

PublicMethod_InvokesService1(){}
PublicMethod_InvokesService2(){}
PublicMethod_InvokesService3(){}
PublicMethod_InvokesService4(){}

这意味着您可以避免在单个方法中拥有所有这些巨大的模拟/断言链。

  • 您可能认为这很天真,因为 - 操作顺序怎么样 - 当然它会变得太困惑,无法确保调用顺序正确,通过 Mocks 将返回值从 Method1 传递到方法 2 怎么样?等等

  • 在这种情况下,如果需要以严格的顺序调用这些服务,那么您还可以考虑,您确实应该使用层次结构,而不是简单的依赖项列表

即代替

PublicClass depends on Service 1 (depends on Service2,3 and 4)

你有

PublicClass depends on Service 1 (depends on Service2 (depends on Service 3 (depends on Service 4))))
  • 这意味着操作顺序不适用;从公共(public)向下的每个服务仅调用单个依赖项,这意味着您无需担心顺序。事实上,在编写公共(public)方法之前,您就已经在结构上强制执行操作的逻辑顺序。

只是我的 2c。

关于java - 如何对调用私有(private)方法链的方法进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21744005/

相关文章:

java - 如何将文本值存入数组?

java - 找不到合适的驱动程序错误

ruby - JRuby 和 Test::Unit 的 assert_raise

java - 在以下情况下我应该如何编写 JUnit 测试?

java - Maven 多模块项目中的 JUnit 测试抛出 NoClassDefFoundError

android - 如何使用 Mockito.mockStatic 在 kotlin android 中模拟静态方法

java套接字保持 Activity 很慢,重新打开套接字更快

java - 用整数填充(树)集的最短方法?

angular - 如何使用 Jasmine 在 Angular 2 中对警报进行单元测试?

java.lang.NoClassDefFoundError : groovy/lang/GroovyObject 错误