Testing Overview
Every module generated by Modulus includes three dedicated test projects. The scaffolded test projects come pre-configured with the right packages, a clean folder structure, and a baseline set of architecture tests -- you can start writing tests immediately after running modulus add-module.
Test Project Types
| Project | Suffix | Purpose |
|---|---|---|
| Unit Tests | Tests.Unit | Test handlers, validators, and domain logic in isolation |
| Integration Tests | Tests.Integration | Test endpoints and data access with real infrastructure |
| Architecture Tests | Tests.Architecture | Enforce layer dependency rules and coding conventions |
Project Naming Convention
Test projects are named {ModuleName}.Tests.{Type} (namespaces are {SolutionName}.{ModuleName}.Tests.{Type}) and live inside the module's own directory:
src/Modules/Catalog/tests/
├── Catalog.Tests.Unit/
├── Catalog.Tests.Integration/
└── Catalog.Tests.Architecture/They are grouped under /tests/Modules/Catalog/ in the solution file. The solution root's tests/ directory holds the solution-level projects scaffolded by modulus init ({Solution}.Tests.Common, {Solution}.Tests.Architecture, {Solution}.Tests.Integration).
Packages
All test projects are scaffolded with the following packages:
| Package | Purpose |
|---|---|
xunit | Test framework |
xunit.runner.visualstudio | Visual Studio / CLI test runner |
Microsoft.NET.Test.Sdk | .NET test host |
Shouldly | Fluent assertion library |
Unit test projects additionally include:
| Package | Purpose |
|---|---|
FluentValidation | Validator testing (TestValidate) |
Architecture test projects additionally include:
| Package | Purpose |
|---|---|
NetArchTest.Rules | Fluent API for enforcing architectural constraints |
Integration test projects additionally include:
| Package | Purpose |
|---|---|
Microsoft.AspNetCore.Mvc.Testing | WebApplicationFactory for hosting the app in tests |
Microsoft.EntityFrameworkCore.InMemory | In-memory EF Core provider for lightweight test doubles |
Testcontainers.MsSql | Docker-based SQL Server for test isolation |
ModulusKit.Testing | Messaging test harness, test transport, and outbox/inbox assertion helpers -- see ModulusKit.Testing |
No mocking framework is scaffolded -- the generated tests exercise real objects. If your team prefers mocks, add NSubstitute or Moq to the unit test project yourself (see Unit Testing). For messaging, prefer ModulusKit.Testing's TestMessageTransport and ModulusMessagingTestHarness over hand-rolling a fake IMessageTransport or writing raw OutboxDbContext/InboxDbContext queries -- see ModulusKit.Testing.
Running Tests
Run all tests from the solution root:
dotnet testRun tests for a specific module:
dotnet test src/Modules/Catalog/tests/Catalog.Tests.UnitRun only architecture tests:
dotnet test --filter "FullyQualifiedName~Tests.Architecture"Run only unit tests:
dotnet test --filter "FullyQualifiedName~Tests.Unit"Run tests in CI
The scaffold does not generate a CI workflow -- add dotnet test to your pipeline of choice so architecture tests catch dependency violations before they reach production.
Test Organization
Tests within each project are organized to mirror the module's structure. The CLI scaffolders follow this convention too -- add-command, add-query, and add-entity each drop a starter test into the matching folder:
Catalog.Tests.Unit/
├── Commands/
│ └── CreateProductHandlerTests.cs
├── Queries/
│ └── GetProductByIdHandlerTests.cs
└── Domain/
└── ProductTests.csThis convention makes it easy to find the test for any given class. The test class name mirrors the class under test with a Tests suffix.
What's Next
Dive into the specific testing guides:
- Architecture Tests -- Enforce layer dependency rules with NetArchTest and Roslyn analyzers
- Unit Testing -- Test handlers, validators, and domain logic in isolation
- Integration Testing -- Test endpoints end-to-end with WebApplicationFactory
- ModulusKit.Testing -- Test messaging module-to-module with a real pipeline instead of hand-rolled fakes