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(...)都非常昂贵,我想重构该类以在一个请求中创建所有项目..让我们进行更改

public class OrderService implements IOrderService
{
    private Set<OrderLine> createOrderItems(List<ProductDto> products)
    {
        Set<OrderLine> orderLines = new HashSet<>();
        BatchItemCreationResponse response = itemService.createAll(products);
        for (ProductDto product : products) {
            Item item = response.get(product.id, product.price);
            ...
        }
        return orderLines;
    }
}

现在我已经进行了更改,并且我之前编写的测试失败了,即使该类的行为根本没有改变。

我错过了什么吗?我必须接受它的方式并简单地调整笔试吗?

任何想法表示赞赏

4

1 回答 1

1

我错过了什么吗?我必须接受它的方式并简单地调整笔试吗?

不,是的。

单元测试确实发生了变化。您已经根据某个类设置了测试以利用某些合同 ( ItemService)。更改此合同要求您更改测试,就这么简单。

换个角度想一想:从测试类客户的角度来看,没有任何改变,行为是相同的(这很好)。但是,从ItemService客户的角度来看,您已经引入了重大变更(合同变更)。客户是谁ItemService?在这种情况下,OrderService及其测试。

此外,您应该考虑状态验证(断言OrderService产品状态)是否比行为验证(调用验证模拟)更合适。前者通常会使您的测试对此类更改不那么脆弱,但两者都不会使引入更改的需要消失。

于 2012-07-05T11:27:18.363 回答