【问题标题】:How to verify the number of private method calls in a constructor?如何验证构造函数中私有方法调用的数量?
【发布时间】:2013-11-27 21:04:46
【问题描述】:

我有以下课程:

public class LegacyClass()
{
    public LegacyClass(final int aModeOfOperation)
    {
        if (aModeOfOperation == 0)
        {
            addSomeValues();
            addSomeValues();
        }
        else if (aModeOfOperation == 1)
        {
            addSomeValues();
        }
    }

    private void addSomeValues()
    {
    }
}

我想写一个单元测试来检查

  1. 调用LegacyClass(0) 导致私有方法addSomeValues 被调用2 次并且
  2. 调用LegacyClass(1) 导致私有方法addSomeValues 被调用一次。

我知道可以在 Mockito/PowerMockito 中使用 spy 对象来计算私有方法调用的次数,但是 AFAIK 这些方法仅在相关方法被调用之后被测试的类。

是否可以在不改变LegacyClass的构造函数的情况下编写上述单元测试?

【问题讨论】:

  • 如果您正在测试私有方法,那么您通常会测试错误的东西。你能测试一下addSomeValues() 被调用两次时会发生什么的结果吗?黑盒测试 > 白盒测试,甚至在类级别。
  • @vikingsteve 测试结果是我现在使用的解决方案,因为我找不到更好的解决方案。
  • 太好了,我认为您实际上找到了更好的解决方案。如果有人重构了LegacyClass,那么你的测试应该仍然是绿色的!

标签: java unit-testing mocking mockito powermock


【解决方案1】:

如果您可以对公共方法的要求/行为执行基于状态的测试 (http://blog.jayfields.com/2008/02/state-based-testing.html?m=1),而不是测试私有方法的调用次数,我认为您从单元测试中获得了更好的价值。这在某些隔离框架中可能是可能的,但从单元测试的角度来看,我认为没有多大价值。

想想一些单元测试,你会验证一个方法已经被调用,或者一个方法被调用了 x 次。这些测试是验证测试,它们仍然有效。但关键因素是大多数模拟对象框架允许您针对公共方法(至少在 .net 中)进行这些验证。原因是私有方法从单元测试的角度来看并不重要,因为它们是内部实现细节。尽量避免代码原理图更改导致测试失败。

【讨论】:

    【解决方案2】:

    我认为不可能使用 mockito,因为您以这种方式声明间谍 spy(new LegacyClass()),因此您的构造函数在对象被间谍之前被调用。也许有一种使用 PoweverMock 的方法,但我通常不鼓励使用 PowerMock,因为没有努力将代码重构为正确的设计。

    相反,我强烈建议您将遗留代码重构为更可测试的代码(测试驱动开发是他的关键)。

    如果您绝对需要使用兼容更改但不使用 PowerMock 保留此遗留代码;我会首先将可见性级别提高到 package visible :

    private void addSomeValues() { ... }
    

    然后在您的测试中编写LegacyClass 的静态子类,并覆盖addSomeValues 方法,该方法将增加调用super 的计数器。

    public class LegacyCodeTest {
      ...
    
      static class AddSomeValuesCounteringLegacyClass extends LegacyClass {
        public int counter;
        void addSomeValues() { counter = counter + 1; super.addSomeValues(); }
      }
    }
    

    然后在你的测试中你满足这个类并断言调用计数;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-11
      • 2021-09-19
      相关资源
      最近更新 更多