Skip to main content

Architecture tests: Logiswift.Eos.ArchitectureTests

Enforces the modular-monolith layering rules (see Architecture Overview) in CI, via NetArchTest.Rules — a violation fails dotnet test the same as any other broken test, rather than only being caught by code review. Lives in tests/Logiswift.Eos.ArchitectureTests/, referencing every src/ project (it only reads their assembly metadata, never calls into them).

What's covered

LayerDependencyTests.cs has one [Fact] per rule, so a break names the specific rule rather than just "architecture test failed":

  • Domain has zero project references and zero infrastructure packages (EF Core, SQL client, RabbitMQ, Redis, MailKit, Azure/Graph/Identity, ASP.NET Core).
  • Application depends only on Domain and never on EF Core.
  • Infrastructure never depends on Api/Api.External/Workers.
  • The three composition roots never depend on each other.
  • Controllers/jobs never depend on Infrastructure.Persistence.Scaffolded directly — the "never touch scaffolded entities directly" rule from the database-first conventions.
  • No module under Infrastructure/Persistence/Repositories/{Auth,Automation, Com,Edi,Ext,Mas,Tms,Wms} depends on another module's repository namespace — this holds even inside one deployment unit, since it's exactly the boundary that has to already hold if a module is ever split into its own service later.

:::note Table-prefix groupings, not Application/Modules/ names The module boundary this rule enforces is the table-prefix grouping under Repositories/, not Application/Modules/'s names — the two don't line up 1:1. See Architecture Overview's "Modules" section. :::

:::caution Composition-root checks use plain reflection, not HaveDependencyOn Logiswift.Eos.Api is a string-prefix of Logiswift.Eos.Api.External — NetArchTest matches dependency namespaces by prefix, so checking "Api.External doesn't depend on Logiswift.Eos.Api" via NetArchTest self-matches every type in Api.External's own Logiswift.Eos.Api.External.* namespace and false-positives with no real dependency at all. The composition-root-vs- composition-root checks use plain Assembly.GetReferencedAssemblies() exact-name comparison instead. Every other rule above has no such name collision and uses NetArchTest directly. :::

What's not covered

[RepositoryWriteStrategy]/module-folder conventions, the Reference-CRUD- pattern shape, and other structural (not layering) rules documented elsewhere are still enforced by code review, not this project.

Reference files

tests/Logiswift.Eos.ArchitectureTests/LayerDependencyTests.cs.