Testujte vašu architektúru pomocou NetArchTest
Máte definovaný na projekte typ architektúry? Onion / Clean / Vertical Slice / ... architektúru?
Prípadne máte vlastné architektonické pravidlá?
Ako si overujete že sú dodržiavané?
Máme .editorconfig
, Roslynator, SonarCloud, ... Ale na architektúru toto nestačí.
Riešením môže byť použitie knižnice NetArchTest.
Táto knižnica umožňuje definovať rôzne pravidlá pre architektúru a následne ich priebežne overovať pomocou unit testov.
O aké pravidlá sa jedná? Najlepšie na príkladoch:
- doménova vrstva nesmie obsahovať závislosti na iných vrstvách
- prístup k databáze môže byť iba v infraštruktúrnej vrstve
- value objekty musia byť immutable
- repositáre musia mať sufix
Repository
- DTO triedy nesmú byť použité v doménovej a infraštruktúrnej vrstve
async
metódy nesmú mať návratový typvoid
a suffixAsync
- a mnoho ďalších pravidiel ktoré na vašom projekte môžu byť dôležité
Ako na to?
- Pridáme referenciu na knižnicu
NetArchTest
do testovacieho projektu.
dotnet add package NetArchTest.Rules
- Vytvoríme unit testy, ktoré budú overovať naše pravidlá.
[Fact]
public void RepositoriesShouldBeLocatedInInfrastructureNamespace()
{
var result = Types.InAssembly(typeof(ProductRepository).Assembly)
.That()
.ImplementInterface(typeof(IRepository)) // 👈 rule for repositories
.Should()
.ResideInNamespaceEndingWith("Infrastructure") // 👈 use rule
.GetResult();
result.IsSuccessful.Should().BeTrue();
}
[Fact]
public void DomainShouldNotReferenceInfrastructure()
{
var result = Types.InAssembly(typeof(ProductDto).Assembly)
.That()
.ResideInNamespace("EShop.Domains")
.ShouldNot()
.HaveDependencyOn("EShop.Infrastructure")
.GetResult();
result.IsSuccessful.Should().BeTrue();
}
- Môžeme si vytvoriť aj vlastné pravidlá.
public class IsRecordRule : ICustomRule
{
// 👇 use custom rule for checking if type is Record
public bool MeetsRule(TypeDefinition type)
=> type.GetMethods().Any(m => m.Name == "<Clone>$");
}
public static class CustomRules
{
// 👇 extension method to simplify the use of a custom rule
public static ConditionList BeRecord(this Conditions conditions)
=> conditions.MeetCustomRule(new IsRecordRule());
}
[Fact]
public void DtoShouldBeRecordType()
{
var result = Types.InAssembly(typeof(ProductDto).Assembly)
.That()
.HaveNameEndingWith("Dto")
.Should()
.BeRecord()
.GetResult();
result.IsSuccessful.Should().BeTrue();
}