Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 测试中的If语句_Java_Unit Testing - Fatal编程技术网

Java 测试中的If语句

Java 测试中的If语句,java,unit-testing,Java,Unit Testing,我有一个参数化的测试类,其中包含一系列单元测试,这些测试通常控制自定义电子邮件消息的创建。现在类有很多测试,这些测试取决于参数化类中使用的因子,每个测试的测试流程都是相同的。测试示例如下: @Test public void testRecipientsCount() { assertEquals(3, recipientsCount); } 我不得不在我的email类中添加额外的功能,将一些额外的内部电子邮件添加到收件人列表中,这种情况只在某些情况下发生,这导致了我的问题 假设我想要

我有一个参数化的测试类,其中包含一系列单元测试,这些测试通常控制自定义电子邮件消息的创建。现在类有很多测试,这些测试取决于参数化类中使用的因子,每个测试的测试流程都是相同的。测试示例如下:

@Test
public void testRecipientsCount() {
    assertEquals(3, recipientsCount);
}
我不得不在我的email类中添加额外的功能,将一些额外的内部电子邮件添加到收件人列表中,这种情况只在某些情况下发生,这导致了我的问题

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

@Test
public void testRecipientsCount(){
    if(something) {
        assertEquals(3, recipientsCount);
    }
    else {
        assertEquals(4, recipientsCount);
    }
}
...
但是我更有经验的同事说我们应该避免在测试课上使用ifs(我对此有点同意)

我认为在两个测试类上拆分测试可能有效,但这将导致两个类中的冗余代码(我仍然需要检查是否创建了非iternal消息、它们的大小、内容等),并为其中一个添加了几行代码


我的问题是:如何做到这一点,以避免使用if或大量冗余代码(不使用参数化类将产生更多冗余代码)?

在我看来,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);
}
}
抽象类YourBusinessObjectAssert{
公共静态无效资产yourbussinessobjectisvalid(YourBusinessObject pYourBusinessObject,集合YourBusinessObject){
for(YourBusinessObject lYourBusinessObject:pAllYourBusinessObject){
if(lyUrbusinessObject.isTechnicalEqual(pYourBusinessObject)){
返回;
}
}
assertFalse(“在列表中找不到请求的YourBusinessObject!”,true);
}
}

它将降低代码的复杂性,并使其他开发人员可以使用它。

在我看来,单元测试应该尽可能只测试一件事。因此,我想说,如果您需要一个if语句,那么您可能需要不止一个单元测试——if/else代码中的每个块都需要一个单元测试

如果可能的话,我会说一个测试应该读起来像一个故事——我喜欢的布局(这不是我的想法——它被广泛使用)是:


单元测试的另一个优点是,当失败发生时,其原因是明确的——如果您有一个具有许多可能结果的长测试,那么很难解释测试失败的原因。

为什么不使用一个私有方法来测试每种方法的共同点?类似于(但可能带有
testCommonStuff()
方法的一些输入参数):


这样你就不会得到多余的代码,你可以把你的测试分成更小的测试。此外,如果您的测试实际上应该测试相同的东西,那么您的测试就不那么容易出错。您仍将知道哪个测试失败,因此可追溯性应该没有问题。

我不确定是否有可能在参数化测试中干净地执行您想要的操作。如果您需要基于某些特性的哪个参数的不同测试用例行为,您最好单独测试这些特性-在未参数化的不同测试类中

如果您确实希望将所有内容都保存在参数化测试类中,我倾向于创建一个helper函数,这样您的示例测试至少可以读取为一个简单的断言:

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

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

将一些额外的内部电子邮件添加到收件人列表中
。这是注入类的内部地址列表吗?如果是这样的话,您只需为大多数测试擦除该列表,并有一个或两个
testInternalMail
测试填充该列表。我认为这在参数化测试类中是不可能的。您建议添加的测试用例将针对每一组参数运行,并且对于某些参数,断言会有所不同。您的解决方案在没有参数化类的情况下可以工作,但我有点想避免这种情况。您可以将发布的代码更改为更完整(但仍然很小且虚假)的测试类,以便我们了解您如何设置参数吗?我使用参数化类,它将为每一组参数运行两个测试用例。正确的方法是只运行一个,这取决于实际参数。@Badman6我不完全明白。您会说“但这将导致两个类中的冗余代码(我仍然必须检查是否创建了非iternal消息、它们的大小、内容等)”。这不意味着在一个或多个测试方法中有冗余代码吗?如果是这样,您可以将它放在一个自己的私有方法中,如上面所述,并从应该运行它的每个方法调用它。收件人计数取决于参数类的参数提供程序中指定的参数。如果我想保留参数化的类,冗余代码将是将我的测试分成两个类的结果(一个用于有内部接收者的情况,一个没有内部接收者)。对于测试类,共享代码实际上不是一个选项。您的解决方案还可以,只是不适合参数化class@Badman6我还是不完全明白。:)如果您确实有冗余代码,那么应该可以将其移动到单独的方法。如果不是的话,对我来说这听起来并不是多余的。
@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
}
@Test
public void testRecipientsCount(){
    assertEquals(expectedCount(something), recipientsCount)
}

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