Junit测试继承,好还是坏?讨论

时间:2016-04-26 07:13:26

标签: java unit-testing junit

我正在寻找用尽可能简单和尽可能少的代码来测试接口的不同实现的意见。我已经实现了很多方法之一。我将使用继承来实现它。

如果您在网上搜索此内容,您会发现许多文章告诉您包含继承是错误的,因为它更难以阅读和理解,并且“始终”测试应该是一长串代码并且它的剂量如果有很多重复的代码就没关系了。 测试这种方式的一个好处是,在testImpls必须实现的抽象方法的帮助下,很容易测试实现之间的差异。

无论如何,我希望你在我的路上能够测试一种接口的两种不同实现。 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.
  }
}

Impl Cloud:

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;
}
}

Impl Local:

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;
}
}

那么您认为,这是一种测试不同impls的好方法,还是用两个简化它来更好地用重复断言进行测试?

1 个答案:

答案 0 :(得分:1)

这里没有对错的答案;归结为偏好和精确的情况。以下是关于一般方法的几点想法(完全披露:我强烈地参与"组成胜过继承"阵营):

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

  • 实用程序方法:这些实际上并不属于类 - 只需将它们放在一个单独的类中,然后在具体的测试类中创建一个实例。
  • 设置/拆除类型方法:这些可以在基类中,但它不灵活,就像Java中的继承通常不灵活一样:你只能扩展一个类,所以如果你想添加更多的话,你就会陷入困境。

    JUnit4提供Fixtures,可用于设置常见内容;它们有点像mixins。语法有点冗长,但是这种冗长会带来灵活性。