【问题标题】:stubbing private method in JavaJava中的存根私有方法
【发布时间】:2012-04-18 16:15:50
【问题描述】:

我正在测试一个函数,它需要几个参数,并根据它们的值调用不同的私有方法。

我想检查函数是否总是调用正确的私有方法。

因为我知道私有方法会做什么,所以我可以检查最终结果,但直接检查是否调用了正确的函数会更方便,因为我已经测试了私有方法。

有没有办法用存根替换私有方法?

【问题讨论】:

  • 在方法开始时在控制台打印函数名。这样你就知道调用了什么函数了。
  • 好的,这是调试而不是测试...
  • @vikiiii:我认为这违背了自动化单元测试的理想。
  • 为什么不想检查结果?多个方法会返回相同的结果吗?

标签: java unit-testing


【解决方案1】:

是的,有一些模拟库可以让你做到这一点。一个是PowerMock。从他们的private method tutorial,你需要这样的东西:

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyUnit.class)
public class TestMyUnit {

    @Test
    public void testSomething() {
        MyUnit unit = PowerMock.createPartialMock(MyUnit.class, "methodNameToStub");
        PowerMock.expectPrivate(unit, "methodNameToStub", param1).andReturn(retVal);

        EasyMock.replay(unit);

        unit.publicMethod(param1);

        EasyMock.verify(unit);

    }

}

但是,我自己真的不同意这种做法。您的单元测试应该测试输入、输出和副作用,仅此而已。通过确保正确调用 private 方法,您所做的就是防止您的代码被轻易重构。

换句话说,如果你想改变如何你的单位是如何工作的呢?执行此操作的安全方法是确保代码处于(通过)测试中,然后重构代码(可能包括更改调用的内部方法),然后再次运行测试以确保您没有破坏任何东西。使用您的方法,这是不可能的,因为您的测试测试的是确切的实现,而不是单元本身的行为。重构几乎总是会破坏测试,那么测试到底能给你带来多少好处呢?

大多数情况下,您会想要这样做,因为您实际上将这些私有方法视为自己的一个单元(这听起来像您,因为您说您已经直接测试了这些私有方法!)。如果是这种情况,最好将该逻辑提取到它自己的类中,对其进行测试,然后在剩余的代码中与该新单元的模拟/存根版本进行交互。如果你这样做了,你的代码就会有更好的结构,而且你不需要依赖 PowerMock 的巫术魔法。 Michael Feathers 的Working Effectively with Legacy Code 是进行此类重构的绝佳参考。

【讨论】:

  • 我没有在 PowerMock 中找到有关它的内容。测试私有方法的方法很多,但没有办法做我需要的事情。但也许我看起来不够努力
  • @delamere:链接确实说它可以模拟私有方法。您可能希望将其与部分模拟结合使用。
  • 这是一个链接:code.google.com/p/powermock/wiki/MockPrivate。在该示例中(测试具有调用私有方法的公共方法的类),他们将带您部分模拟该类,然后对私有方法设置期望。
【解决方案2】:

您可以检查 java 工具来这样做

【讨论】:

【解决方案3】:

作为解决方案之一,可以使用内部类的代理。您需要在每个必须测试的类中添加内部类。 但对于大型产品项目来说,这不是很好的解决方案。它需要创建添加脚本以从您的发布文件(jar/war)中删除生成的类。

但更简单的方法将使用 PowerMock,如 cmets bellow(or upper :)) - http://code.google.com/p/powermock/wiki/MockPrivate

【讨论】:

    【解决方案4】:

    是否可以为相关类提供另一个对象,将私有方法移至该对象并使其公开?在这种情况下,很容易为该接口创建一个测试假人。

    【讨论】:

      【解决方案5】:

      如果调用正确的“私有方法”没有可观察到的外部结果,您确定要对此进行测试吗?也许不应该。

      如果无论私有方法是否被调用,最终结果都相同,并且您仍想观察其调用,则可以将该方法设为公共并将其移至其自己的类,然后模拟该类。然后您可以验证(使用 Mockito 或类似框架)您的方法是否被调用。

      【讨论】:

        【解决方案6】:

        代码覆盖工具通过在测试实际运行之前重写字节码来做这种事情。所以,它必须是可能的,但它不是微不足道的。

        更新:编写一个要求调用“正确”私有方法的单元测试会使重构工作变得非常痛苦,因为您必须重新编写所有测试。这违背了测试的目的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-20
          相关资源
          最近更新 更多