子类模拟对象

时间:2020-01-09 10:35:39  来源:igfitidea点击:

子类模拟对象是通过将要测试的类子类化并覆盖其某些方法而创建的模拟对象。让我们看一个简单的类:

public class MyUnit {

  protected MyDependency dependency = null;

  public MyUnit(MyDependency dep) {
    this.dependency = dep;
  }

  public void doTheThing(String param) {

    if("one".equals(param)) {
      dependency.callOne();
    } else {
      dependency.callTwo();
    }
  }
}

MyUnit类是我要进行单元测试的类。在这个单元测试中,我想检查MyUnit类是否正确调用MyDependency类。有3种方法可以做到这一点:

  • 使用代理对象创建MyDependency类的Mock实现
  • 创建MyDependency类的子类模拟,并覆盖callOne()和callTwo()方法
  • 创建MyUnit类本身的子类,并在测试期间使用它。

在本文中,我将向我们展示如何进行nr。 3.如果需要,从该方法中很容易弄清楚如何做2号。

使用方法nr。 3需要执行以下步骤:

  • 将对MyDependency的调用封装在MyUnit中
  • 创建MyUnit的子类
  • 覆盖MyDependency调用封装方法。

在本文的其余部分中,我将向我们展示如何执行这三个步骤。

步骤1:封装对MyDepedency的调用

首先要做的是重构MyUnit类,以便所有对MyDependency类的调用都封装在它们自己的方法中。看起来是这样的:

public class MyUnit {

  protected MyDependency dependency = null;

  public MyUnit(MyDependency dep) {
    this.dependency = dep;
  }

  public void doTheThing(String param) {

    if("one".equals(param)) {
      callOne();
    } else {
      callTwo();
    }
  }

  protected void callOne() {
      dependency.callOne();
  }

  protected void callTwo() {
      dependency.callTwo();
  }
}

注意,对MyDependency.callOne()和MyDependency.callTwo()的两个调用现在如何封装在两个受保护的方法中,分别是callOne()和callTwo()。

现在我们准备创建MyUnit子类。

步骤2:创建MyUnit的子类模拟

第二步是创建MyUnit类的子类模拟。这里是:

public MyUnitMock extends MyUnit {

  protected boolean callOneCalled = false;
  protected boolean callTwoCalled = false;

  @Override
  protected void callOne() {
    this.callOneCalled = true;
    super.callOne();
  }

  @Override
  protected void callTwo() {
    this.callTwoCalled = true;
    super.callTwo();
  }

}

通过将布尔值设置为true,请注意两个被覆盖的方法如何记录是否调用它们。

下一步是在单元测试中使用" MyUnitMock"。

步骤3:在单元测试中使用MyUnitMock类

这是一个使用MyUnitMock类的单元测试方法:

@Test
public void test() {
   MyUnitMock myUnitMock = new MyUnitMock();

   myUnitMock.doTheThing("one");

   assertTrue (myUnitMock.callOneCalled);
   assertFalse(myUnitMock.callTwoCalled);

   //reset mock before next call
   myUnitMock.callOneCalled = false;

   myUnitMock.doTheThing("two");

   assertFalse(myUnitMock.callOneCalled);
   assertTrue (myUnitMock.callTwoCalled);
}

首先,创建MyUnitMock类的实例。其次,调用doTheThing()方法。第三,断言是否调用了callOne()和callTwo()方法。

概括

如我们所见,如上所述,可以通过使用子类模拟来测试几乎所有类。但是,在某些情况下,最好将完全独立的模拟依赖对象与原始类一起使用。确切的时间,取决于具体的应用。