I am currently working on what you could categorise as a workflow automation product.
The product is comprised of independently deployed front and back end components.
The core domain is realised by a single .Net Core solution.? The front end interacts with it via a REST API and it interacts with further components (and occasionally itself) using messaging.
Two core aspects of the internal design are Entity Framework for data access and extensive use of the mediator pattern.
Using mediator, every element of the solution is broken down into sets of 3 classes, request, handler and result.? Requests and results are POCOs whilst handlers implement behaviour and require few dependencies. ?Often, in cases where the only job to do is orchestrate the sending and receiving of requests and results, the sole dependency is the mediator type itself.? Other requests fall into the two categories of query or command.
All told a well thought out and pleasant stack to work in.? Mediator leads to few dependencies, which in turn leads to simple classes that are easy to drive with tests.
Except for the fact that nothing is ever quite as simple as one would like.
There is a problem writing tests in this solution in that to test a simple isolated query the test setup must replay all the steps the application would theoretically take in order to reach the point whereby the query can return sensible results when issued against Entity Framework over an in memory database.
This is achieved by gathering and then issuing a collection of steps, where each step is a high-level mediator message, as the ¡°Given¡±s and ¡°When¡±s of a test scenario.? During the ¡°Then¡± assertions are made against the result POCOs that were observed by a stub implementation of the mediator type, e.g. assert that the last created entity of type ¡°A¡± should have such and such an ¡°A.Name¡±.
I believe the goal of the approach is to use the real application code to avoid making assumptions about the state of the system when writing tests, however the more steps required to reach a the prerequisite snapshot of state, the greater the reliance on developers writing new tests to comprehend the set of steps that should be replayed in order to reach the point from which they want to proceed.
It feels to me as though what has gone wrong here is that although the application code has a nicely decoupled architecture the database and/or the Entity Framework domain model layer does not and as a result entities depend on other entities in a way that makes them intrinsically co-dependent.? This interdependency is revealed by tests which cannot drive simple code without themselves being complicated.
I thought perhaps I could lean on the experience in this group to gain some suggestions on how to reduce this kind of test friction?
Paul