242
CHAPTER 6 | Tackle Business Complexity in a Microservice with DDD and CQRS Patterns
namespace
Microsoft.
eShopOnContainers
.
Services
.
Ordering
.
Infrastructure
.
Repositories
{
public
class
OrderRepository : IOrderRepository
{
// ...
}
}
Each specific repository interface implements the generic IRepository interface:
public
interface
IOrderRepository : IRepository
{
Order
Add
(Order order);
// ...
}
However, a better way to have the code enforce the convention that each repository is related to a
single aggregate is to implement a generic repository type. That way, it’s explicit that you’re using a
repository to target a specific aggregate. That can be easily done by implementing a generic
IRepository
base interface, as in the following code:
public
interface
IRepository where T : IAggregateRoot
{
//....
}
The Repository pattern makes it easier to test your application logic
The Repository pattern allows you to easily test your application with unit tests. Remember that unit
tests only test your code, not infrastructure, so the repository abstractions make it easier to achieve
that goal.
As noted in an earlier section, it’s recommended that you define and place the repository interfaces in
the domain model layer so the ap
plication layer, such as your Web API microservice, doesn’t depend
directly on the infrastructure layer where you’ve implemented the actual repository classes. By doing
this and using Dependency Injection in the controllers of your Web API, you can implement mock
repositories that return fake data instead of data from the database. This decoupled approach allows
you to create and run unit tests that focus the logic of your application without requiring connectivity
to the database.
Connections to databases can fail and, more importantly, running hundreds of tests against a
database is bad for two reasons. First, it can take a long time because of the large number of tests.
Second, the database records might change and impact the results of your tests, especially if your
tests are running in parallel, so that they might not be consistent. Unit tests typically can run in
parallel; integration tests may not support parallel execution depending on their implementation.
Testing against the database isn’t a unit te
st but an integration test. You should have many unit tests
running fast, but fewer integration tests against the databases.
In terms of separation of concerns for unit tests, your logic operates on domain entities in memory. It
assumes the repository class has delivered those. Once your logic modifies the domain entities, it
assumes the repository class will store them correctly. The important point here is to create unit tests
243
CHAPTER 6 | Tackle Business Complexity in a Microservice with DDD and CQRS Patterns
against your domain model and its domain logic. Aggregate roots are the main consistency
boundaries in DDD.
The repositories implemented in eShopOnContainers rely on EF Core’s DbContext implementation of
the Repository and Unit of Work patterns using its change tracker, so they don’t duplicate this
functionality.
Dostları ilə paylaş: