2017-05-19 32 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