Expert guidance for building .NET microservices using Tactical Domain-Driven Design patterns with .NET Aspire, xUnit testing, and snapshot verification.
Apply Tactical Domain-Driven Design principles when building .NET microservices with .NET Aspire orchestration.
This skill guides you to implement microservices using Tactical DDD building blocks (Entities, Aggregates, Value Objects, Domain Services, Application Services) with proper test coverage using xUnit and snapshot testing.
1. **Always use Tactical DDD patterns**:
- **Entities**: Objects with unique identity that persist over time
- **Aggregates**: Clusters of entities with a single aggregate root
- **Value Objects**: Immutable objects defined by their attributes
- **Domain Services**: Domain logic that doesn't belong to a single entity
- **Application Services**: Orchestrate domain objects and use cases
2. **Enforce invariants at aggregate boundaries**
3. **Keep aggregates small and focused**
4. **Use value objects for concepts without identity** (money, addresses, etc.)
1. **Use xUnit for all tests**:
- Do NOT use `using Xunit;` namespace declaration
- Do NOT use `using VerifyXunit;` namespace declaration
- Both are implicitly available in modern .NET
2. **Use VerifyXunit for snapshot assertions**:
- Do NOT add `[UsesVerify]` attribute
- Use `Verify()` method directly (NOT `Verifier.Verify()`)
3. **Always structure tests with AAA pattern**:
```csharp
[Fact]
public async Task TestName()
{
// Arrange
var dependency = new Dependency();
// Act
var result = await sut.DoSomething();
// Assert
await Verify(result);
}
```
4. **Always cover functionality with tests**:
- Unit tests for domain logic
- Integration tests for application services
- Test edge cases and business rules
1. Use .NET Aspire for orchestration and service discovery
2. Leverage Aspire's built-in observability
3. Configure service dependencies in AppHost project
**Domain Model:**
```csharp
// Value Object
public record ProductId(Guid Value);
// Entity
public class Product : Entity<ProductId>
{
public string Name { get; private set; }
public Money Price { get; private set; }
public void UpdatePrice(Money newPrice)
{
if (newPrice.Amount <= 0)
throw new DomainException("Price must be positive");
Price = newPrice;
}
}
```
**Test:**
```csharp
public class ProductTests
{
[Fact]
public async Task UpdatePrice_ValidPrice_UpdatesSuccessfully()
{
// Arrange
var product = new Product(new ProductId(Guid.NewGuid()), "Widget", Money.FromUsd(10));
var newPrice = Money.FromUsd(15);
// Act
product.UpdatePrice(newPrice);
// Assert
await Verify(product);
}
}
```
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/tactical-ddd-for-net-microservices/raw