【问题标题】:Mock inner final object模拟内部最终对象
【发布时间】:2023-03-12 11:59:01
【问题描述】:

我正在尝试为预先存在的课程编写测试。

class ClassToBeTested {

  private final Obj1 a;

  ClassToBeTested(String anotherVariable) {

     a = new Obj1(anotherVariable);
  }

 public void methodToBeTested() {

     if(invokeSomeOtherMethod()) {
          a.getAnotherVariable().doSomething();
     } 
 }

 public boolean invokeSomeOtherMethod() { 
         // return true or false based on some logic
 }

 Obj1 getObj1() {
     return a;
 }

}

下面是我的测试类:

class TestClass {


    @Test
    public void testMethod() {

        ClassToBeTested x = new ClassToBeTested("someString");
        ClassToBeTested spyX = spy(x);
        doReturn(false).when(spyX).invokeSomeOtherMethod();

        spyX.methodToBeTested();
        verify(spyX, times(1)).getObj1().doSomething();

    }
}

这是我的理解: 由于 obj1 是在类构造函数中创建的私有最终对象,因此它既不能在测试方法中直接访问,也不能强制 spyObject 使用 obj1 的模拟版本。

此外,由于 verify() 需要 obj1 的模拟版本,因此会引发错误: Wanted But Not invoked: x.getObj1(), however there are otherInteractions with this mock: x.invokeSomeOtherMethod()

我的理解错了吗?测试 testMoethod() 的方法是什么?

【问题讨论】:

  • 修改构造函数以便注入a
  • 我想避免这种情况,因为它需要跨项目中的多个文件进行更改。 a 的初始化也不直接依赖于调用它的代码,因为 anotherVariable 只是一个当前未使用的字符串。
  • 我不明白你的代码。你的类只显示了一个构造函数——没有没有参数的构造函数。但是您在测试方法中使用了没有参数的构造函数。哪个是对的?
  • 对不起...我的错误...已纠正...有一个字符串参数的构造函数。
  • 您的问题是您在 spyX 对象上调用 verify,而您正在尝试验证对 Obj1 对象的方法调用。可能最简单的做法是添加第二个构造函数,在其中传入Obj1 而不是String。然后在您的测试中使用第二个构造函数,并传入一个模拟 Obj1,然后您可以对其进行验证。

标签: java unit-testing mocking mockito


【解决方案1】:

您似乎不明白如何进行正确的依赖注入。您无需更改所有代码以使其更易于测试 - 只需使用构造函数伸缩即可:

class ClassToBeTested {

  private final Obj1 a;

  public ClassToBeTested(String anotherVariable) {
   this(new Obj1(anotherVariable));
  }

  ClassToBeTested(Obj1 a) {
    this.a = a;
  }

完成。现在你有一个包保护的构造函数,你可以使用它直接插入 a 的实例。您的所有其他生产代码都可以保持原样。

换句话说:不要通过使用模拟框架技巧来“修复”您的设计问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多