测试抽象类和模板方法模式

摘自Wikipedia,“模板方法定义了算法的程序框架。 子类可以覆盖一个或多个算法步骤,以允许不同的行为,同时确保仍然遵循总体算法。”

通常,此模式由两个或多个类组成,一个是提供模板方法(非抽象)的抽象类,该模板方法具有对由一个或多个具体子类实现的抽象方法的调用。

模板抽象类和具体实现通常位于同一项目中,但是根据项目范围,这些具体对象将被实现到另一个项目中。

在这篇文章中,我们将看到在外部项目上实现具体类时如何测试模板方法模式,或更一般的如何测试抽象类。

让我们看一个简单的模板方法模式示例。 考虑一个负责接收整数向量并计算欧几里得范数的类。 这些整数可以从多个来源接收,并留给每个项目以提供一种获取它们的方法。

模板类如下所示:

public abstract class AbstractCalculator {

 public double euclideanNorm() {

  int[] vector = this.read();

  int total = 0;

  for(int element:vector) {
   total+= (element*element);  
  }

  return Math.sqrt(total);
 }

 public abstract int[] read();
}

现在,另一个项目可以扩展上一类,并通过提供read()方法的实现来实现抽象计算器。

public class ConsoleCalculator extends AbstractCalculator {

 public int[] read() {

  int [] data = new int[0];

  Scanner scanner = new Scanner(System.in);

  //data = read requried data from console

  return data; 

 }

}

编写了具体实现的开发人员将只测试read()方法,他可以“相信”抽象类的开发人员已经测试了非抽象方法。

但是,如果类是抽象的并且需要read()方法的实现,我们将如何在计算方法上编写单元测试?

第一种方法可能是创建伪造的实现:

public class FakeCalculator extends AbstractCalculator {

 private int[] data;

 public FakeCalculator(int[] data) {
  this.data = data;
 }

 public int[] read() {
  return this.data;
 }

}

这不是一个坏方法,但是有一些缺点:

  • 测试的可读性较低,读者应该知道这些假类的存在,并且必须确切地知道他们在做什么。
  • 作为测试作者,您将花费时间来实现伪类,在这种情况下,这很简单,但是您的项目可能有多个不执行任何抽象类,甚至使用不止一个抽象方法。
  • 伪造类的行为是“硬编码的”。

更好的方法是使用Mockito仅模拟抽象方法,同时调用非抽象方法的实现。

public class WhenCalculatingEuclideanNorm {

 @Test
 public void should_calculate_correctly() {

  AbstractCalculator abstractCalculator = mock(AbstractCalculator.class, Mockito.CALLS_REAL_METHODS);

  doReturn(new int[]{2,2}).when(abstractCalculator).read();
  assertThat(abstractCalculator.euclideanNorm(), is(2.8284271247461903));

 }

 @Test
 public void should_calculate_correctly_with_negative_values() {

  AbstractCalculator abstractCalculator = mock(AbstractCalculator.class, Mockito.CALLS_REAL_METHODS);

  doReturn(new int[]{-2,-2}).when(abstractCalculator).read();
  assertThat(abstractCalculator.euclideanNorm(), is(2.8284271247461903));

 }

}

Mockito通过调用真实方法简化了抽象类的测试,并且仅对抽象方法进行了存根处理。 看到这种情况是因为默认情况下我们正在调用真实方法,而不是使用典型的when()then()结构,而是必须使用doReturn模式。

当然,仅当您的项目不包含算法的具体实现,或者您的项目将成为另一个项目的第3方库的一部分时,才可以使用此方法。 在其他情况下,解决问题的最佳方法是测试实现的类。

下载源代码

参考:One Jar to Rulem All博客上测试了我们的JCG合作伙伴 Alex Soto的抽象类(尤其是模板方法模式)


翻译自: https://www.javacodegeeks.com/2012/06/testing-abstract-classes-and-template.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值