java - 为什么要避免单元测试中的条件逻辑以及如何避免?

标签 java unit-testing testing junit automated-tests

<分区>

假设有以下类:

public class Product {
   private String name;
   private double price;

   // Constructors, getters and setters
}

public class Products {
   private List<Product> products;

   // CRUD methods

   public double getTotalPrice() {
      // calculates the price of all products
   }
}

我读到在单元测试中应该避免条件逻辑(if 和循环),但不明白为什么,更重要的是如何理解。如何在不使用循环的情况下高效地测试在 Products 中添加一些产品并验证 getTotalPrice() 的结果的场景?

最佳答案

对条件和循环的恐惧有两方面:

  1. 您的测试代码中可能存在错误,因此测试无法正常运行,或者更糟的是,条件 block 内的断言未断言。
  2. 它更难阅读。

其他人的回答是通过复制和粘贴对列表进行硬编码。我不喜欢那样,因为它不仅会使测试困惑,而且使以后重构变得更加困难。

如果代码像 Invisible Arrow 的答案一样:

@Test
public void testsTotalPriceAsSumOfProductPrices() {
    Products products = new Products(); // Or any appropriate constructor
    products.add(new Product("first", 10)); // Assuming such a constructor exists
    products.add(new Product("second", 20));
    products.add(new Product("second", 30));
    assertEquals("Sum must be eq to 60", 60, products.getTotalPrice());
}

并且 Product 的构造函数发生了变化,您将不得不在许多不同的地方更改所有测试代码。

我更喜欢制作辅助方法,使测试代码更能揭示意图,并将重构期间更改的位置数量保持在最低限度(希望只有一个)。

这不是更容易阅读吗:

 @Test
public void testsTotalPriceAsSumOfProductPrices() {
    Products products = new Products(); 

    addProductsWithPrices(products, 10,20,30);

    assertEquals(60, products.getTotalPrice());

}

private static void addProductsWithPrices(Products products, Double...prices){
  for(Double price : prices){
     //could keep static counter or something
     //to make names unique
     products.add(new Product("name", price));
  }
}

是的,这确实使用了 for 循环。但是如果你担心它有错误或者辅助方法更复杂,你也可以为它们编写额外的测试!最终,您可能希望将这些辅助方法分解到它们自己的类中,以便它们可以在其他测试中重用。

此外,您还可以看到测试方法隐藏了与测试无关的制作产品所需的其他字段(名称)。我们的测试只关心价格,所以我们的助手只是编造名字,阅读测试的人不会被额外的参数弄糊涂。很明显,这个测试确保 10+20+30 ==60。

最后,如果我们将价格从 double 更改为某种 Currency 对象,我们只需在一个地方进行更改,我们的测试代码就像可读。

 private static void addProductsWithPrices(Products products, Double...prices){
  for(Double price : prices){
     //could keep static counter or something
     //to make names unique
     products.add(new Product("name", Currency.valueOf(price)));
  }
}

关于java - 为什么要避免单元测试中的条件逻辑以及如何避免?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27880631/

相关文章:

PHPUnit:数据提供者问题

java - spring项目中大量的数据库迁移

java - 无法从 XPathExpression<Object> 转换为 XPathExpression<Content>

java - 在jsp中显示多个BufferedImage

c# - 使用 PostSharp 进行正确的单元测试

java - 测试数据分离

css - 如何测试 CSS 解析器?

java - Spring 安全: Access is Denied Exception

java - 用java实现摊销程序

c++ - C/C++涉及2个进程时如何使用fake function framework?