复杂 Java 模型的 JUnit 测试

JUnit test for complex Java Models

我想 learn/know 我如何使用 JUnit 测试复杂的 java classes。

我有一个 java 项目,我正在其中读取属性文件中的内容 ,然后我将文件的内容解析为 java 个对象。属性文件具有树结构,因此我已经实现了 Java 模型以及复合模式。

那么,当我想为复合 class 或项目的任何 class 编写单元测试时,我应该如何编写这些测试?测试应该是什么样子的?它应该看起来像这样吗?

 @Test
 public void testComposition()
 {
     // Create a object of the Composite class, what you expect after reading
     // from the file
     Composite expectedObject = new Composite();
     ...

     // Call the parser class of the file which returns a composite
     Composite createdObject = PropertiesFileParser.parse(file);

     // and then i have to assert the 2 object with a method from Assert 
     // e.g.
     assertEqual(createdObject, expectedObject);
 }

我是否必须创建预期的复合对象 expectedObject "by hand"?或者还有其他方法可以做这样的事情吗?

在编写Junit 测试用例时是否有一些编码约定?

感谢每一个有帮助的回答! (请原谅我的英语)

首先,您应该检查 object 的每个方法。所以,如果我是你,我会通过调用 leaf 和 composite 的各个方法来检查一个小模型的一些微不足道的情况。例如,我会:

  1. 创建合成。
  2. 确保它没有 children.
  3. 确保它优雅地拒绝删除不属于它的 child。
  4. 添加一个child.
  5. 确保它有一个 child。
  6. 确保它仍然优雅地拒绝删除不属于它的 child。
  7. 再添加一个child.
  8. 确保它有两个 children.
  9. 确保它优雅地拒绝添加它已经包含的 child。
  10. 去掉第一个child.
  11. 确保它有一个 child。
  12. 删除第二个child。
  13. 确保它没有 children.
  14. 确保它优雅地拒绝删除它不再拥有的 child。

然后,您需要编写一些测试来确保您的 object 的 equals() 方法绝对正确地工作,因为稍后这个方法将被 junit 的 assertEqual()。所以,如果我是你,我会:

  1. 创建单个object A.
  2. 创建 A 的副本作为 B。
  3. 确保 A 等于 B。
  4. 创建一个 A 的副本作为 C 并稍微更改它。
  5. 确保 A 不等于 C。
  6. 创建 A 的副本作为 D 并稍微更改它。
  7. 确保 A 不等于 D。
  8. 创建一个 A 的副本作为 E 并稍微更改它。
  9. 确保 A 不等于 E。

...依此类推,直到您确信您的 Leaf.equals()Composite.equals() 方法中绝对没有任何未经测试的事情发生。

然后,您应该手动测试微小层次结构的基础知识。所以:

  1. 创建一个小层次结构 A。(只有一个 parent 和一个 child。)
  2. 创建一个与 A 相同的小层次结构 B。
  3. 确保 A 等于 B。
  4. 创建一个在细节上与 A 不同的小层次结构 X。
  5. 确保 A 不等于 X。
  6. 创建一个小的层次结构 Y,它在另一个微小的细节上与 A 不同。
  7. 确保 A 不等于 Y。
  8. 创建一个小的层次结构 Z,它在另一个微小的细节上与 A 不同。
  9. 确保 A 不等于 Z。

完成以上所有操作后,就可以打盘了。

写入磁盘是为了确保模型的复杂实例仍然有效。你可以写一个PropertiesFileWriter来写一个层次结构到一个文件,所以你可以创建一个object层次结构,把它写到一个文件中,然后把文件读到另一个object层次结构中,然后比较两个 object 层次结构。

要使测试非常简单和可读,您可以创建类似这样的东西

@Test
 public void testComposition()
 {
     // given
     Composite expectedObject = getExpectedComposite();

     // when
     Composite createdObject = PropertiesFileParser.parse(file);

     // then
     assertTrue(areCompositesEquals(createdObject, expectedObject));
 }

private Composite getExpectedComposite() {
    Composite composite = new Composite();
    // construct a composite you expect after reading from file

    return composite;
}


private static boolean areCompositesEquals(Composite createdObject,
        Composite expectedObject) {

    // assert...
    // assert...
    // assert...
    // list of asserts here that check the composites are equals (number of children and other condition)

    return true;
}

为了避免在您的磁盘上进行 I/O 操作,您可以为您的测试文件创建 mock。