【问题标题】:Testing wrapper class测试包装类
【发布时间】:2015-11-26 17:03:38
【问题描述】:

我想测试一个用作为下面的类提供抽象的包装器的类。

这意味着我需要在该类中创建一些对象,也就是说,我不通过构造函数或某些方法传递协作者。

例如,这是一个包装类:

public class Abstraction {

      private ComplexClass complex;

      public class Abstraction(some parameters) {
           complex = new Complex(parameters);
      }

}

为了能够测试这个类,我想到了创建一个返回 Complex 类对象的方法,如下所示:

public class Abstraction {

      private ComplexClass complex;

      public class Abstraction(parameters) {
           complex = createComplex(parameters);
      }

      protected createComplex ComplexClass(parameters) {
           return new ComplexClass(parameters);
      }
}

问题是,我不能使用 Mockito 来模拟在我正在测试的类的构造函数中创建的协作者。如何克服?

我的想法是监视 SUT,以便 createComplex 返回模拟对象,但我不能这样做,因为需要先创建 SUT。这有点像死锁。

我的最终目标是测试是否调用了协作者类的某些方法。

【问题讨论】:

    标签: java unit-testing mocking mockito


    【解决方案1】:

    测试这个类有什么商业优势?它没有实现算法,也没有做出决定。正如你所说,它只是一个包装器。

    您说您想测试是否调用了某些方法,但这对任何人有什么帮助?当然,确认方法在某些情况下被调用而不在其他情况下被调用的测试,换句话说,对业务逻辑的测试会更有用。这里的风险是你最终会得到一个难以维护的复杂测试,并引入惯性,这将使未来的重构变得更加困难和昂贵。你希望得到什么样的回报才能使这种风险变得有价值?

    【讨论】:

    • 我实际上对测试不是很有经验,我还在学习,所以我对你这样的 cmets 持开放态度。那么你会推荐什么,而不是测试它?
    • 一个好的测试可以证明某些代码的行为方式应该如此。如果代码简单明了,(或什么都不做),则不需要测试。
    • +1 在这里。测试这种类的唯一可能原因是你有一个不称职的经理,他坚持一定的代码覆盖率。
    【解决方案2】:

    你可以在你的测试用例中使用一个相当简单的匿名内部类来做到这一点

    ComplexClass mock = Mockito.mock(ComplexClass.class);
    Abstraction abstraction = new Abstraction("foo") {
        @Override
        protected ComplexClass createComplex(parameters) {
           return mock;
        }
    };
    assertTrue("bar", abstraction.doStuff());
    

    【讨论】:

      【解决方案3】:

      您可以为您在Abstraction 上设置的ComplexClass 实现factory

      public class ComplexClassFactory {
          public ComplexClass create(parameters) {
              return new ComplexClass(parameters);
          }
      }
      
      public class Abstraction {
      
          private ComplexClassFactory complexClassFactory; 
      
          public void setComplexClassFactory(ComplexClassFactory complexClassFactory) {
              this.complexClassFactory = complexClassFactory;
          }
      
          private ComplexClass complex;
      
          public class Abstraction(parameters) {
             complex = complexClassFactory.create(parameters);
          }
      }
      

      【讨论】:

        【解决方案4】:

        一种可能性是为ComplexClass 类(我将其命名为Complex)提取一个接口,并提供一个备用构造函数,仅用于测试目的,以注入新创建的@ 的实例987654323@接口:

            public class Abstraction {
        
                private Complex complex;
        
                public Abstraction(String parameters) {
                    this.complex = new ComplexClass(parameters);
                }
        
                Abstraction(Complex complex) {
                    this.complex = complex;
                }
        
                public class ComplexClass implements Complex {
        
                    private final String parameters;
        
                    public ComplexClass(String parameters) {
                        this.parameters = parameters;
                    }
                }
        
                interface Complex {
                }
        
            }
        

        这样您可以为Complex 接口创建一个模拟,使用接收Complex 实例的构造函数并独立测试Abstraction 类:

        @Test
        public void testAbstraction() {
            Complex mock = Mockito.mock(Complex.class);
            Abstraction abstraction = new Abstraction(mock);
        }
        

        【讨论】:

          猜你喜欢
          • 2015-03-16
          • 1970-01-01
          • 1970-01-01
          • 2014-03-22
          • 2012-02-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-08-26
          相关资源
          最近更新 更多