Reputation: 183
I'm designing a small application using Symfony2, with a DDD domain conceived as a vendor. This allows me to abstract my domain by not making any assumptions on what uses it. Basically, this domain is a set of business entities and services which perform their internal stuff. The business operations are called from the outside (Symfony controllers) by simple facades that do not expose anything from the domain.
Now, I would like to test my domain to validate its business rules. Given that this domain can't work on its own as it needs concrete repositories implementations, I set up my tests to use mocks of these repositories. My question is : how can I validate all the domain actions which are performed internally ?
For instance, suppose my domain is made of two entities : Article
and Category
. I can traverse an article to get its category, but I can't traverse a category to get its articles as it doesn't make sense in the context of my domain. Now, I have a business rule that states that whenever a category is disabled, all the articles on this category should be disabled as well.
The entry point for this action would be a disable($category)
method on a CategoryFacade
service. This action would first disable the category, then fetch all the articles of this category and disable them.
If I call the disable()
action from a test case, I can validate that my category was correctly disabled as it is the actual object on which I am performing the test. But what about the articles ? I don't have a getArticles()
method on my category, and since my domain only uses mocks as repositories, it wouldn't make any sense to fetch manually the articles and asserting on them.
Edit
The answer proposed below reminded me of something critical. Indeed, in my example, a category is to be considered as an AR as it has an existence outside the scope of an article. But since an article is an AR as well, it should be entirely responsible for its own consistency. That means that the deactivation of all articles linked to a category should not be initiated by a category service, as this service shouldn't know anything about articles. My choice will be the one proposed below : dispatch en event whenever a category is disabled, and perform deactivation on articles in a service which is inside the boundaries of my article.
Upvotes: 0
Views: 211
Reputation: 7322
In first place it is best to not test repositories togheter with domain logic and since repositories should be used only in application layer, then you shoudln't test application services. If you have to, then just create some test repository (memory based). You should test your business rules just on domain objects. In example if you want to test if user rating works fine then do:
rated_user = UserFactory(parameters)
assertEqual(rated_user.rating, Rating(0))
rating_user = UserFactory(parameters)
rating_value = 3
rating_user.rateUser(rated_user, rating)
assertEqual(rated_user.rating, Rating(3))
Testing of your case is difficult because ARs should be changed in different transactions (probably even not in the same request). From what you say it seems that Category should be an AR (aggregate root), because in order to disable category we have to fetch one category without using an article to do so. Now when you disable category, you should send event that articles should get and disable itself then. You can test if articles are disabled just by calling EventListener callback, that would be better IMHO. Testing both ARs togheter would be actually an integration test, which requires more setup.
Anyway, to test if all articles of a given category are disabled, you have to fetch them, probably using something like "articlesRepository.getArticlesOfCategory(category)" and check one by one if it's disabled. There is no other way.
Upvotes: 1