To bring a specific example, I have PromoCode
Aggregate Root that consists of PromoCodeUsage
Entity which is only controlled by that AR, so that some methods on AR are simply delegated to that Entity, like:
public function useFor(Order $order): void
{
$this->promoCodeUsage->useFor($order);
}
And some of them are partly delegated, like:
public function applyFor(Order $order): void
{
if (!$this->published) {
throw new NotPublishedPromoCodeCanNotBeApplied();
}
$this->promoCodeUsage->applyFor($order);
}
My test suite fully covers all PromoCode
behavior including PromoCodeUsage
functionality, because at that iteration there was no PromoCodeUsage
and all logic was mixed in PromoCode
. Then I refactored some of that logic into PromoCodeUsage
. This test suite for PromoCode
had many tests and I was happy I can split it too (but it worked well even after splitting entities). So I created another test suite (PromoCodeUsageTest
), where I moved part of tests from PromoCode.
But PromoCodeUsageTest
s are testing PromoCodeUsage
entity through the behavior of PromoCode
, same way like it was in original test before splitting. They are not touching PromoCodeUsage
directly. Now I have PromoCodeTest
suite with:
And PromoCodeUsageTest suite with:
But it is somehow weird, that 1) in PromoCodeTest
I omit some tests (that are elsewhere) and 2) in PromoCodeUsageTest
I am actually not touching PromoCodeUsage
entity. 3) I use Roy Osherove’s template for test naming, and I do not know what method name should I use in test name - from PromoCode or PromoCodeUsage? In my case they are same but they could differ and that idea smells.
If I rewrite PromoCodeUsageTest
s to test directly PromoCodeUsage
entity, I end up with some uncovered methods on PromoCode
(that are just delegated to PromoCodeUsage
). So that takes me back to my approach to test PromoCodeUsage
through PromoCode
AR.
Uncle Bob (and others) says it is good practice to test behavior, not API. Does my approach head to conform to that?
Because I feel some smell in my approach, do you? How to do it better?