### Install ArchUnitNET Package Source: https://github.com/tng/archunitnet/blob/main/README.md Install the core ArchUnitNET package using the NuGet package manager. This is the first step to using ArchUnitNET in your project. ```powershell PS> Install-Package TngTech.ArchUnitNET ``` -------------------------------- ### Install ArchUnitNET Extension Packages Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Install ArchUnitNET extension packages for specific unit test frameworks like MSTestv2, xUnit, or NUnit. ```powershell PS> Install-Package TngTech.ArchUnitNET.MSTestV2 PS> Install-Package TngTech.ArchUnitNET.xUnit PS> Install-Package TngTech.ArchUnitNET.NUnit ``` -------------------------------- ### Install ArchUnitNET Unit Test Extensions Source: https://github.com/tng/archunitnet/blob/main/README.md Install the appropriate ArchUnitNET extension package for your chosen unit testing framework (xUnit, NUnit, MSTestV2). This integrates ArchUnitNET with your test runner. ```powershell PS> Install-Package TngTech.ArchUnitNET.xUnit ``` ```powershell PS> Install-Package TngTech.ArchUnitNET.xUnitV3 ``` ```powershell PS> Install-Package TngTech.ArchUnitNET.NUnit ``` ```powershell PS> Install-Package TngTech.ArchUnitNET.MSTestV2 ``` -------------------------------- ### Check Layer and Forbidden Interface Rules Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Verifies that example classes reside in the correct layer and forbidden interfaces are in their designated layer. It also shows how to combine multiple rules. ```cs [Fact] public void TypesShouldBeInCorrectLayer() { IArchRule exampleClassesShouldBeInExampleLayer = Classes().That().Are(ExampleClasses).Should().Be(ExampleLayer); IArchRule forbiddenInterfacesShouldBeInForbiddenLayer = Interfaces().That().Are(ForbiddenInterfaces).Should().Be(ForbiddenLayer); // Check if your architecture fulfills your rules exampleClassesShouldBeInExampleLayer.Check(Architecture); forbiddenInterfacesShouldBeInForbiddenLayer.Check(Architecture); // You can also combine your rules IArchRule combinedArchRule = exampleClassesShouldBeInExampleLayer .And(forbiddenInterfacesShouldBeInForbiddenLayer); combinedArchRule.Check(Architecture); } ``` -------------------------------- ### NotHaveNameStartingWith Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide/predicate/object.md Asserts that a type's name does not start with the specified pattern. ```APIDOC TReturnType NotHaveNameStartingWith(string pattern); ``` -------------------------------- ### NotHaveNameStartingWith Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide/condition/object.md Checks if an object's name does not start with the specified pattern. ```APIDOC ## NotHaveNameStartingWith ### Description Checks if an object's name does not start with the specified pattern. ### Method Signature ```csharp TReturnType NotHaveNameStartingWith(string pattern); ``` ``` -------------------------------- ### PlantUML Component Diagram Example Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md An example PlantUML component diagram illustrating component definitions and dependencies. This diagram can be used with ArchUnitNET's AdhereToPlantUmlDiagram rule. ```plantuml @startuml [Model] <> [Controller] <> [Controller] --> [Model] @enduml ``` -------------------------------- ### Create ArchUnitNET Test Class Source: https://github.com/tng/archunitnet/blob/main/README.md Set up a test class using xUnit and ArchUnitNET. Load your architecture once for performance. Define reusable object providers for layers, classes, and interfaces. ```cs using ArchUnitNET.Domain; using ArchUnitNET.Loader; using ArchUnitNET.Fluent; using Xunit; //add a using directive to ArchUnitNET.Fluent.ArchRuleDefinition to easily define ArchRules using static ArchUnitNET.Fluent.ArchRuleDefinition; namespace ExampleTest { public class ExampleArchUnitTest { // TIP: load your architecture once at the start to maximize performance of your tests private static readonly Architecture Architecture = new ArchLoader().LoadAssemblies( System.Reflection.Assembly.Load("ExampleClassAssemblyName"), System.Reflection.Assembly.Load("ForbiddenClassAssemblyName") ).Build(); // replace and with classes from the assemblies you want to test //declare variables you'll use throughout your tests up here //use As() to give them a custom description private readonly IObjectProvider ExampleLayer = Types().That().ResideInAssembly("ExampleAssembly").As("Example Layer"); private readonly IObjectProvider ExampleClasses = Classes().That().ImplementInterface("IExampleInterface").As("Example Classes"); private readonly IObjectProvider ForbiddenLayer = Types().That().ResideInNamespace("ForbiddenNamespace").As("Forbidden Layer"); private readonly IObjectProvider ForbiddenInterfaces = Interfaces().That().HaveFullNameContaining("forbidden").As("Forbidden Interfaces"); //write some tests [Fact] public void TypesShouldBeInCorrectLayer() { //you can use the fluent API to write your own rules IArchRule exampleClassesShouldBeInExampleLayer = Classes().That().Are(ExampleClasses).Should().Be(ExampleLayer); IArchRule forbiddenInterfacesShouldBeInForbiddenLayer = Interfaces().That().Are(ForbiddenInterfaces).Should().Be(ForbiddenLayer); //check if your architecture fulfils your rules exampleClassesShouldBeInExampleLayer.Check(Architecture); forbiddenInterfacesShouldBeInForbiddenLayer.Check(Architecture); //you can also combine your rules IArchRule combinedArchRule = exampleClassesShouldBeInExampleLayer.And(forbiddenInterfacesShouldBeInForbiddenLayer); combinedArchRule.Check(Architecture); } [Fact] public void ExampleLayerShouldNotAccessForbiddenLayer() { //you can give your rules a custom reason, which is displayed when it fails //(together with the types that failed the rule) IArchRule exampleLayerShouldNotAccessForbiddenLayer = Types().That().Are(ExampleLayer).Should () .NotDependOnAny(ForbiddenLayer).Because("it's forbidden"); exampleLayerShouldNotAccessForbiddenLayer.Check(Architecture); } [Fact] public void ForbiddenClassesShouldHaveCorrectName() { Classes().That().AreAssignableTo(ForbiddenInterfaces).Should().HaveNameContaining("forbidden") .Check(Architecture); } [Fact] public void ExampleClassesShouldNotCallForbiddenMethods() { Classes().That().Are(ExampleClasses).Should().NotCallAny( MethodMembers().That().AreDeclaredIn(ForbiddenLayer).Or().HaveNameContaining("forbidden")) .Check(Architecture); } } } ``` -------------------------------- ### Check Architecture Rule with xUnit/NUnit Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Demonstrates how to check an architecture rule using the ArchUnitNET xUnit/NUnit extension. ```cs IArchRule someRule = ...; someRule.check(Architecture); ``` -------------------------------- ### Build Structured Diagram with Packages Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Creates a PlantUML component diagram that includes package structure, suitable for smaller projects or when a more organized view is needed. Uses MatchingWithPackages for slice rule definition. ```cs string pattern = "ArchUnitNET.(**)"; GivenSlices sliceRule = SliceRuleDefinition.Slices().MatchingWithPackages(pattern); Architecture arch = new ArchLoader().LoadAssembly(typeof(ArchUnitNET.Domain.Architecture).Assembly).Build(); string path = "diagram.puml"; PlantUmlDefinition.ComponentDiagram().WithDependenciesFromSlices(sliceRule.GetObjects(arch)).WriteToFile(path); ``` -------------------------------- ### Check if Class is Sealed Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide/condition/attribute.md Use this condition to check if a class is sealed. No setup is required. ```csharp TReturnType BeSealed(); ``` -------------------------------- ### Declare Layers with Object Providers Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Define layers and class collections using ArchUnitNET's object providers. Use As() to assign custom descriptions for better readability in test results. ```csharp // Use As() to give your variables a custom description private readonly IObjectProvider ExampleLayer = Types().That().ResideInAssembly("ExampleAssembly").As("Example Layer"); private readonly IObjectProvider ExampleClasses = Classes().That().ImplementInterface("IExampleInterface").As("Example Classes"); private readonly IObjectProvider ForbiddenLayer = Types().That().ResideInNamespace("ForbiddenNamespace").As("Forbidden Layer"); private readonly IObjectProvider ForbiddenInterfaces = Interfaces().That().HaveFullNameContaining("forbidden").As("Forbidden Interfaces"); ``` -------------------------------- ### Check if Class is Abstract Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide/condition/attribute.md Use this condition to check if a class is abstract. No setup is required. ```csharp TReturnType BeAbstract(); ``` -------------------------------- ### Generate PlantUML Diagram with Focus Mode Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Creates a PlantUML diagram that highlights dependencies related to a specific package. This 'focus mode' can show all dependencies on or out of the specified package. ```cs string pattern = "ArchUnitNET.(**)"; string focusOnThisPackage = "ArchUnitNET.Fluent.Syntax.Elements" GivenSlices sliceRule = SliceRuleDefinition.Slices().MatchingWithPackages(pattern); Architecture arch = new ArchLoader().LoadAssembly(typeof(ArchUnitNET.Domain.Architecture).Assembly).Build(); string path = "diagram.puml"; PlantUmlDefinition.ComponentDiagram().WithDependenciesFromSlices(sliceRule.GetObjects(arch), focusOnThisPackage).WriteToFile(path); ``` -------------------------------- ### Check if Class is Not Sealed Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide/condition/attribute.md Use this condition to check if a class is not sealed. No setup is required. ```csharp TReturnType NotBeSealed(); ``` -------------------------------- ### Check if Class is Not Abstract Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide/condition/attribute.md Use this condition to check if a class is not abstract. No setup is required. ```csharp TReturnType NotBeAbstract(); ``` -------------------------------- ### Build Full Dependency Diagram with PlantUML Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Generates a PlantUML component diagram showing all dependencies within a specified pattern. Ensure the ArchUnitNET.Domain.Architecture class is from your target assembly. ```cs string pattern = "ArchUnitNET.(**)"; GivenSlices sliceRule = SliceRuleDefinition.Slices().Matching(pattern); //Replace ArchUnitNET.Domain.Architecture with any class from your pattern Architecture arch = new ArchLoader().LoadAssembly(typeof(ArchUnitNET.Domain.Architecture).Assembly).Build(); string path = "diagram.puml"; PlantUmlDefinition.ComponentDiagram().WithDependenciesFromSlices(sliceRule.GetObjects(arch)).WriteToFile(path); ``` -------------------------------- ### Build Limited Dependencies Diagram Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Generates a simplified PlantUML diagram showing dependencies only between packages at the same slice level. Set GenerationOptions LimitDependencies to true for maximum simplification. ```cs string pattern = "ArchUnitNET.(**)"; GivenSlices sliceRule = SliceRuleDefinition.Slices().MatchingWithPackages(pattern); Architecture arch = new ArchLoader().LoadAssembly(typeof(ArchUnitNET.Domain.Architecture).Assembly).Build(); GenerationOptions g = new GenerationOptions(){LimitDependencies = true}; string path = "diagram.puml"; PlantUmlDefinition.ComponentDiagram().WithDependenciesFromSlices(sliceRule.GetObjects(arch), g).WriteToFile(path); ``` -------------------------------- ### Check Architecture Rule without Extension Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Shows how to check an architecture rule and assert its validity without using the xUnit/NUnit extension. ```cs IArchRule someRule = ...; bool checkedRule = someRule.HasNoViolations(Architecture); Assert.True(checkedRule); ``` -------------------------------- ### Load Architecture Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Load the architecture of specified assemblies using ArchLoader. This should be done once to maximize test performance. ```csharp private static readonly Architecture Architecture = new ArchLoader().LoadAssemblies( System.Reflection.Assembly.Load("ExampleClassAssemblyName"), System.Reflection.Assembly.Load("ForbiddenClassAssemblyName") ).Build(); ``` -------------------------------- ### Run ArchUnitNET Tests Source: https://github.com/tng/archunitnet/blob/main/README.md Execute ArchUnitNET tests using the .NET CLI. It is recommended to run tests in Debug configuration for accurate results. ```bash dotnet test -c Debug ``` -------------------------------- ### Derive Rules from PlantUML Diagram Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Illustrates how to derive dependency rules from a PlantUML component diagram. The diagram must use stereotypes to associate types with components. ```cs String myDiagram = "./Resources/my-diagram.puml"; IArchRule someRule = Types().Should().AdhereToPlantUmlDiagram(myDiagram); someRule.Check(Architecture); ``` -------------------------------- ### Enable C4-Style PlantUML Diagrams Source: https://github.com/tng/archunitnet/blob/main/documentation/docs/guide.md Generates a PlantUML diagram in C4 style by setting the C4Style flag to true within GenerationOptions. This provides a different visual representation for system components. ```cs string pattern = "ArchUnitNET.(*).(*).(*)"; GivenSlices sliceRule = SliceRuleDefinition.Slices().MatchingWithPackages(pattern); Architecture arch = new ArchLoader().LoadAssembly(typeof(ArchUnitNET.Domain.Architecture).Assembly).Build(); GenerationOptions g = new GenerationOptions(){C4Style = true}; string path = "diagram.puml"; PlantUmlDefinition.ComponentDiagram().WithDependenciesFromSlices(sliceRule.GetObjects(arch), g).WriteToFile(path); ```