2017-05-19 34 views
0

为了使一个具体的例子,我有PromoCode聚合根是由PromoCodeUsage实体,仅由AR控制,以便在AR一些方法只是委托给该实体,如:如何测试将其调用委托给AR实体的Aggregate Root的方法?

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); 
} 

我的测试套件完全覆盖,包括PromoCodeUsage功能的所有PromoCode行为,因为在那个迭代没有PromoCodeUsage和所有的逻辑在混合。然后我重构了一些逻辑到PromoCodeUsage。这个测试套件为PromoCode进行了很多测试,我很高兴我也可以分解它(但它在分割实体后仍然运行良好)。所以我创建了另一个测试套件(PromoCodeUsageTest),我从PromoCode移动了部分测试。

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

但它是有点怪异,即1)PromoCodeTest我省略了一些测试(在别处)和2)PromoCodeUsageTest我其实不触摸PromoCodeUsage实体。 3)我使用Roy Osherove的模板进行测试命名,我不知道应该在测试名称中使用什么方法名称 - 从PromoCode或PromoCodeUsage?在我的情况下,他们是相同的,但他们可能会有所不同,这个想法有味道

如果我重写PromoCodeUsageTest s到直接测试PromoCodeUsage实体,我结束了在PromoCode一些未覆盖的方法(即只是委托给PromoCodeUsage)。所以这让我回到我的方法来测试PromoCodeUsagePromoCode AR。

Bob叔叔(和其他人)说,测试行为而不是API是很好的做法。我的方法是否符合?

因为我的方法感觉有些异味,对吗?如何做得更好?

+1

http://stackoverflow.com/a/153565/54734 – VoiceOfUnreason

+1

*“在PromoCodeUsageTest我实际上没有触及PromoCodeUsage实体”* - 甚至在断言? – guillaume31

+0

@ guillaume31不,我通过AggregateRoot断言。而且,我并没有太多断言,我宁愿没有断言知道,当我已经测试了引发预期异常的所有情况时,可以在不抛出异常/错误的情况下执行该操作。因为我发现,我需要在我的实体上拥有getter才能执行这些断言,我认为这是不好的,不仅仅是因为只有测试方法,而是因为我会测试API而不是行为。 – Tom

回答

1

想想测试行为是正确的。我假设你的聚合的所有行为都是通过聚合根暴露出来的,所以通过根来测试是有意义的。我只是建议你给你的测试命名,以描述他们正在测试的行为。不要在测试名称中使用方法名称,因为这些名称可能会更改 - 这会将测试名称绑定到生产代码的内部实现。

如果一个测试类变得非常大,将它分成更小的类是有意义的 - 没有规则说明测试类和生产类之间必须有1:1的关系。然而,这可能表明你的班级,在这种情况下你的班级可能有太多的责任,可能会被分解成更小的部分。

+0

不幸的是,我的AR真的需要所有这些,因为它需要原子检查不变量。这并不复杂,因为这些不变量可以通过限制对象动态设置。但是,感谢提示,绝对有助于我的信心和灵感:) – Tom

1

我倾向于将聚合看作状态机并相应地测试它们。

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

当然,这可能需要深入了解整体的内部情况,在依赖实体中。如果你比较喜欢把不同的测试类放在不同的测试类中,那么所有的Asserts看起来都是PromoCodeUsage的测试,那么很好,只要测试名称反映域而不是一些技术细节。

+0

我决定通过PromoCode AR行为来测试所有的测试,但我将测试分成许多由特定类(实体)命名的测试类PromoCode。但我现在坚持如何为PromoCodeUsage中的每个特定的IRestriction命名测试(该服务器是动态业务不变的)。所以我现在来了一些像'XxxOrderSpecificationRestrictionTest'这样的东西,例如'testThroughPromoCodeApplyTo_OrderWithUnfitSpecification_SUTWithEmptyOptions_ShouldNotApply'。但那很奇怪。另外,真正的SUT是什么,XxxOrderSpecificationRestriction或AR我正在测试它? – Tom

+1

我并不完全明白“限制”的含义,但我会说AR仍然是SUT。它要么转变成一个新的国家或者不转型。 – guillaume31