如何测试聚合根的方法,只是将其调用委托给AR的实体?

时间:2017-05-19 02:44:49

标签: unit-testing oop testing tdd domain-driven-design

为了得到一个具体的例子,我有PromoCode聚合根,它由PromoCodeUsage实体组成,仅由该AR控制,因此AR上的某些方法只被委托给该实体,如:

public function useFor(Order $order): void
{
    $this->promoCodeUsage->useFor($order);
}

其中一些部分被委派,如:

public function applyFor(Order $order): void
{
    if (!$this->published) {
        throw new NotPublishedPromoCodeCanNotBeApplied();
    }

    $this->promoCodeUsage->applyFor($order);
}

我的测试套件完全涵盖了所有PromoCode行为,包括PromoCodeUsage功能,因为在那次迭代中没有PromoCodeUsage并且所有逻辑都混合在PromoCode中。然后我将一些逻辑重构为PromoCodeUsage。这个PromoCode的测试套件有很多测试,我很高兴我也可以将它拆分(但是在拆分实体之后它也运行良好)。所以我创建了另一个测试套件(PromoCodeUsageTest),在那里我从PromoCode移动了部分测试。

但是PromoCodeUsageTest正在通过PromoCodeUsage的行为测试PromoCode实体,就像在拆分前的原始测试一样。他们没有直接接触PromoCodeUsage。现在我有PromoCodeTest套房: enter image description here 和PromoCodeUsageTest套件: enter image description here

但它有点奇怪,1)在PromoCodeTest我省略了一些测试(在其他地方)和2)在PromoCodeUsageTest我实际上没有触及PromoCodeUsage实体。 3)我使用Roy Osherove的测试命名模板,我不知道我应该在测试名称中使用什么方法名称 - 来自PromoCode或PromoCodeUsage?在我的情况下,它们是相同的,但它们可能不同,这个想法闻起来。

如果我重写PromoCodeUsageTest来直接测试PromoCodeUsage实体,我最终会在PromoCode上找到一些未被发现的方法(只是委托给PromoCodeUsage)。因此,我回到了通过PromoCodeUsage AR测试PromoCode的方法。

Bob叔叔(和其他人)说测试行为是一种好习惯,而不是API。我的方法是否符合要求?

因为我的方法感觉有些气味,你呢?怎么做得更好?

2 个答案:

答案 0 :(得分:2)

考虑行为是正确的。我假设聚合的所有行为都是通过聚合根公开的,因此通过根进行测试是有意义的。我建议你将测试命名为描述他们正在测试的行为。不要在测试名称中使用方法名称,因为这些名称可能会更改 - 这会将测试名称与生产代码的内部实现联系起来。

如果测试类变得非常大,那么将它分成更小的类是有意义的 - 没有规则要求测试类和生产类之间必须有1:1的关系。但是,这可能表明您的班级以及此案例中的汇总可能会承担太多责任,可能会分成更小的部分。

答案 1 :(得分:1)

我倾向于将Aggregates视为状态机并相应地测试它们。

重要的不在于测试所在的测试文件,而是测试PromoCode聚合的所有可能结果状态,具体取决于您正在执行的启动状态和促销代码使用/应用程序的类型。

当然,这可能需要在依赖实体中深入研究聚合的​​内容。如果你更容易在其他测试类中放入所有Asserts看PromoCodeUsage的测试,那么就好了,只要测试名称反映域而不是一些技术细节。