java - 带继承的 Junit 测试是好是坏?讨论

标签 java unit-testing junit

我正在寻找意见,以使用尽可能简单和尽可能少的代码来测试接口(interface)的不同实现。我已经实现了多种方法之一。我将使用继承来使其成为可能。

如果您在网上搜索这一点,您会发现许多文章告诉您包含继承是错误的,因为它更难阅读和理解,并且“始终”测试应该是一长段代码,而且它确实如此如果有很多重复的代码也没关系。 这种测试方式的好处之一是,借助 testImpls 必须实现的抽象方法,可以轻松测试实现之间的差异。

无论如何,我想听听您对我在这种情况下测试一个接口(interface)的两种不同实现的方式的看法。 impls 之间的区别在于,ImplCloud 将包放在云端,而 implLocal 将包放在磁盘上。

我们将有一个名为 SomeImplAsserts 的断言类以及 impl Local 和 Cloud。 该测试将由三个测试类构建,其中包含注释和一些用于解释的伪代码。

SomeImplAsserts.class ImplCloudTest.class ImplLocalTest.class

public abstract class SomeImplAsserts {
  // Variables that booth implementations need.
  private PathGetter pathGetter;

  // Abstract helper methods. 
  abstract public String getLocalPackagePath(PathGetter pathGetter);

  // Common setup method.
  @Before
  public void setUp() {
  //Setup that's equal for for all impls will be done here.
  }

  @Test
  public void testPackageContent() throws IOException {
  // Place for common assert, asserts where we expect the same value from our implementations will be placed here.

  String pathToPackage = getLocalPackagePath(pathGetter);
  assertEquals("/someTempPath/package.zip", pathToPackage);
  unzip(pathToPackage);

  //asserts on package content.     

  }
  //Common utility methods.
  public void unzip(String abc) throws IOException {
  // unzips the package
  }

  @After
  public void tearDown() {
    //Tear down of all tests will be done here.
  }
}

实现云:

public class ImplCloudTest extends SomeImplAsserts {

@Override
public String getLocalPackagePath(PathGetter pathGetter) {
  // A place where you could write specific asserts for this impl.
  // This Impl puts an package in the cloud, in order to run tests on the content off the file
  // we would like to put it on disk.

  String url = pathGetter.getPath();
  assertTrue(isUrl(url));

  //Create temp dir and download file to it.

  Path temp = Files.createTempDirectory("someTempPath");
  URI u = URI.create(exportUrl);

  InputStream in = u.toURL().openStream();
  String pathToFile = temp.toString().concat("/" + exportUrl.substring(exportUrl.lastIndexOf("/")));
  Files.copy(in, Paths.get(pathToFile));

  return pathToFile;
}
}

实现本地:

public class ImplaLocalTest extends SomeImplAsserts {

@Override
public String getLocalPackagePath(PathGetter pathGetter) {
  // this impl puts the file at the disk to begin with. No need to download it.
  String localPath = pathGetter.getPath();
  assertFalse(isUrl(localPath));

  return localPath;
}
}

那么您认为,这是测试不同 impl 的好方法还是用两个来简化它来测试重复的断言会更好?

最佳答案

这里没有正确或错误的答案;这取决于偏好和具体情况。以下是关于一般方法的一些想法(全面披露:我强烈支持“组合击败继承”阵营):

基类中有两种类型的东西:

  • 实用方法:这些方法并不真正属于类 - 只需将它们放入单独的类中,然后在具体的测试类中创建该类的实例即可。
  • 设置/拆卸类型方法:这些可以位于基类中,但它不灵活,就像 Java 中的继承通常不灵活一样:您只能扩展一个类,所以如果你想添加更多类,你会有点卡住。

    JUnit4 提供 Fixtures ,可以用来设置常用的东西;它们有点像 mixin。语法有点冗长,但繁琐也带来了灵 active 。

关于java - 带继承的 Junit 测试是好是坏?讨论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36857788/

相关文章:

java - 使用 Collector.toMap 在 map 中收集

java - Java 中 Web 服务的安全性

Python 单元测试模拟

junit - Jmeter:使用带变量的 jmeter Junit 请求

java - 如何在 JUnit 测试中引导 weld-se

java - Play Framework : Created WAR file is not zipped up

java - 将 xerces 与 JBOSS EAP 7.1 一起使用时,XSD 1.1 验证失败

c# - 使用Moq进行测试,一行使用异步可查询扩展和项目,如何测试

c# - 如何从 TestContext 获取当前参数值?

spring - 使用 Spring Boot 配置集成测试还是在单元测试中使用 Spring JDBC?