2012-07-05 129 views
1

当我们为更复杂的方法/类编写单元测试时,我还没有那么自信。我对tdd和单元测试一般的理解是,你应该能够重构类/方法的实现,并且有信心你没有改变其行为明确。测试行为和模拟

public class OrderService implements IOrderService 
{ 
    private IItemService itemService; 

    public Order create(OrderCreationDto dto) 
    { 
     Order order = new Order(); 
     order.addItems(createOrderLines(dto.products)); 
     return order; 
    } 

    private Set<OrderLine> createOrderItems(List<ProductDto> products) 
    { 
     Set<OrderLine> orderLines = new HashSet<>(); 
     for (ProductDto product : products) { 
      Item item = itemService.create(product.id, product.price); 
      OrderLine orderLine = new OrderLine(); 
      orderLine.setItemId(item.id); 
      orderLines.add(orderLine); 
     } 
     return orderLines; 
    } 
} 

基本上我只是从OrderCreationDto创建一个新的订单。对于每个订单行,我必须先使用项目服务创建一个新项目。我的一个测试可以确保,每个订单行都有一定的参数调用itemService.create(...)

由于每次调用itemService.create(...)是我想重构类在一个请求中创建的所有项目..让我们做的变化相当昂贵

现在我所做的更改和我以前即使班级的行为完全没有改变,书面测试也会失败。

我错过了什么吗?这是我不得不接受的方式,并且简单地调整书面测试?

任何想法是值得赞赏

+0

但您的方法的执行改变了。这不是你的测试失败的好理由吗? – Schaliasos 2012-07-05 11:36:06

回答

1

我缺少的东西?这是我不得不接受的方式,并且简单地调整书面测试?

是的。

单元测试更改。你已经根据某个类来设置你的测试来利用某个合约(ItemService)。改变这份合同要求你改变测试,就像那样简单。

不同地思考:从测试客户端的角度来看,没有什么改变,行为也是一样的(这很好)。然而,从ItemService客户的角度来看,您已经引入突破变化(合同变更)。谁是ItemService客户端?在这种情况下,OrderService及其测试。

此外,你应该考虑状态验证(声称的OrderService产品状态)是否将不超过动作验证更适合(验证模拟叫)。前者通常会让你的测试对这种变化不那么脆弱,但这两者都不需要引入变化就可以消失。