如果在测试中声明

时间:2013-03-01 09:11:14

标签: java unit-testing

我有一个带有大量单元测试的参数化测试类,通常控制自定义电子邮件的创建。现在类有很多测试,这取决于参数化类中使用的因子,测试的流程对于每个测试都是相同的。测试的例子:

@Test
public void testRecipientsCount() {
    assertEquals(3, recipientsCount);
}

我必须在我的电子邮件类中添加额外的功能,这些功能会在收件人列表中添加一些额外的内部电子邮件,这只会在某些情况下发生,从而导致我的问题。

假设我想断言创建的消息量。对于旧测试,每种情况都是相同的,但现在根据情况不同。对我来说最直观的方法是添加if语句:

@Test
public void testRecipientsCount(){
    if(something) {
        assertEquals(3, recipientsCount);
    }
    else {
        assertEquals(4, recipientsCount);
    }
}
...

但是我更有经验的同事说我们应该避免参加测试课程(并且我有点同意)。

我认为对两个测试classess的拆分测试可能有效,但这会导致两个类中的冗余代码(我仍然需要检查是否创建了非传递消息,它们的大小,内容等),以及一些为其中一个添加了行。

我的问题是:我该如何做到这一点,所以我不使用if或load冗余代码(不使用参数化类会产生更多的冗余代码)?

4 个答案:

答案 0 :(得分:3)

在我看来,Junit应该像协议一样阅读。 这意味着您可以编写冗余代码以使测试用例更易读。 为业务逻辑中的每个可能的if语句以及否定案例编写一个测试用例。这是获得100%测试覆盖率的唯一方法。 我使用的结构:

- testdata preparation
- executing logic
- check results
- clear data

此外,您应该在自己的抽象类中编写大对象的复杂断言:

abstract class YourBusinessObjectAssert{
  public static void assertYourBussinessObjectIsValid(YourBusinessObject pYourBusinessObject,       Collection<YourBusinessObject> pAllYourBusinessObject) {
for (YourBusinessObject lYourBusinessObject : pAllYourBusinessObject) {
  if (lYourBusinessObject.isTechnicalEqual(pYourBusinessObject)) {
    return;
  }
}
assertFalse("Could not find requested YourBusinessObject in List<YourBusinessObject>!", true);
}
}

它将降低代码的复杂性,并且您可以将其提供给其他开发人员。

答案 1 :(得分:0)

在我看来,单元测试应尽可能只测试一件事。因此,我要说如果你需要一个if语句,那么你可能需要多个单元测试 - 一个用于if / else代码中的每个块。

如果可能,我会说测试应该像故事一样 - 我的首选布局(而不是我的想法:-) - 它被广泛使用)是:

- given:  do setup etc
- when:  the place you actually execute/call the thing under test
- expect: verify the result

单元测试只测试一件事的另一个好处是,当发生故障时,其明确的原因是什么 - 如果你有很多可能结果的长测试,那么理由为什么测试失败就变得更难了。 p>

答案 2 :(得分:0)

为什么不使用私有方法来测试每种方法常见的东西?类似的东西(但可能有testCommonStuff()方法的一些输入参数):

@Test
public void testRecipientsCountA(){
   testCommonStuff();
   // Assert stuff for test A
}

@Test
public void testRecipientsCountB(){
   testCommonStuff();
   // Assert stuff for test B
}

private void testCommonStuff() {
   // Assert common stuff
}

这样您就不会获得冗余代码,您可以将测试分成更小的测试。如果他们真的应该测试相同的东西,你也会让你的测试不那么容易出错。你仍然知道哪个测试失败了,所以可追溯性应该没问题。

答案 3 :(得分:0)

我不确定在参数化测试中是否可以干净利落地完成你所做的事。如果您根据某些功能的参数需要不同的测试用例行为,您可能最好单独测试这些功能 - 在不参数化的不同测试类中。

如果你真的想把所有内容保存在参数化测试类中,我会倾向于创建一个辅助函数,这样你的示例测试至少可以读作一个简单的断言:

@Test
public void testRecipientsCount(){
    assertEquals(expectedCount(something), recipientsCount)
}

private int expectedCount(boolean which) {
    if (something){
       return 3;
    }
    else {
       return 4;
    }
}