单元测试断言重复

时间:2011-02-08 07:52:37

标签: unit-testing tdd nunit

我正在研究TDD并在我当前的项目中进行实验。 我注意到我必须在测试中复制很多断言。 这是情况: 我有两个构造函数的Order类,第一个是默认的 第二个有三个参数

Order(int customerId, int typeId, decimal amount)

在OrderTests类中,我正在检查分配是否正常运行

Assert.IsTrue(o.CustomerId == 5 && o.TypeId == 3 && amount == 500)

我的订单服务类有以下创建订单方法,因为订单创建是一个复杂的过程。

Order CreateOrder(int cusotmerId, int typeId, int amount, moreParams...)

OrderServiceTests类测试了这个方法,我需要使用相同的assert来检查Order是否已在CreateOrder服务中正确创建。

Assert.IsTrue(o.CustomerId == 5 && o.TypeId == 3 && amount == 500)
  1. 在测试中是否可以有这样的重复?
  2. 在测试中提取具有相同断言的方法是否有意义,有时数字或重复断言可能多于一个?或者这样的方法提取使测试不可读?

3 个答案:

答案 0 :(得分:4)

如果您有多种方法来创建对象,您可能希望测试每个创建方法的对象状态(即参数化构造函数和工厂方法)。因此,复制断言是有意义的。

在完成测试后重构期间(始终记住口头禅:红绿重构)如果您不仅在生产代码中发现重复,而且在测试中也发现重复,那么您应该通过以下方式将其删除:使用Extract Method重构。

[TestMethod]
public void if_parametrized_ctor_is_called_then_state_should_be_accordingly {
  var order = new Order(customerId, ...);
  ObjectPropertiesShouldBeSetTo(order, customerId, ...);
}

[TestMethod]
public void if_factory_method_is_called_then_state_should_be_accordingly {
  var order = myFactory.CreateOrder(customerId, ...);
  ObjectPropertiesShouldBeSetTo(order, customerId, ...);
}

// Extracted to remove code duplication
public void ObjectPropertiesShouldBeSetTo(Order order, int customerId, ...) {
  Assert.AreEqual(customerId, order.CustomerId);
  Assert.AreEqual(...);
}

如果在一个Assert语句中检查多个条件,则会使事情变得复杂。它会降低测试可读性,如果任何一个条件失败,可能很难找到原因。

答案 1 :(得分:3)

如果您需要为多个测试执行相同的对象验证,则将这些Asserts拆分为常用方法是减少重复的好方法。在上面的示例中,您可以使用一个名为AssertObjectIsValid的方法,并将公共代码移动到那里。

关于您的示例Assert的另一件事。在单个Assert中组合多个检查使得从故障中确定哪个属性出错更加困难。如果将它们拆分为单独的断言,并为每个断言提供消息,它将更容易跟踪错误(特别是如果您使用CruiseControl.Net等持续集成服务器。)修改您的示例:

Assert.IsTrue(o.CustomerID == 5, "CustomerID doesn't match expected");
Assert.IsTrue(o.TypeId == 3, "TypeID doesn't match expected");
Assert.IsTrue(amount == 500, "Amount doesn't match expected");

答案 2 :(得分:1)

是的,单元测试经常导致代码重复。但这种重复有价值。这个想法是,如果你用两种方式写同样的东西,你不可能两次都犯同样的错误。这意味着你会遇到很多愚蠢的错误。 (不可否认,其中一半是在您的单元测试代码中。)从代码中自动生成单元测试会导致所有代码重复,并且带来的好处更少。