User Guide
1. Installation
To use ArchUnitNET, install the ArchUnitNET package from NuGet:
PS> Install-Package ArchUnitNET
If you want to use xUnit or NUnit for your unit tests, you should instead install the corresponding ArchUnit extension:
PS> Install-Package ArchUnitNET.xUnit
PS> Install-Package ArchUnitNET.NUnit
2. Quick Start
Create a test class to start testing. We used xUnit with the ArchUnit extension here, but it works similarly with NUnit or other Unit Test Frameworks.
Find this example code here.
2.1. Directives
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;
2.2. Load Architecture
Load your architecture once at the start to maximize performance of your tests replace <ExampleClass> and <ForbiddenClass> with classes from the assemblies you want to test
private static readonly Architecture Architecture =
new ArchLoader().LoadAssemblies(typeof(ExampleClass).Assembly,
typeof(ForbiddenClass).Assembly).Build();
2.3. Declare Layers
Declare variables you'll use throughout your tests up here
//use As() to give your variables a custom description
private readonly IObjectProvider<IType> ExampleLayer =
Types().That().ResideInAssembly("ExampleAssembly").As("Example Layer");
private readonly IObjectProvider<Class> ExampleClasses =
Classes().That().ImplementInterface("IExampleInterface").As("Example Classes");
private readonly IObjectProvider<IType> ForbiddenLayer =
Types().That().ResideInNamespace("ForbiddenNamespace").As("Forbidden Layer");
private readonly IObjectProvider<Interface> ForbiddenInterfaces =
Interfaces().That().HaveFullNameContaining("forbidden").As("Forbidden Interfaces");
2.4. Test Cases
Testing if above defined "ExampleClasses" reside in "ExampleLayer"
[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);
}
Testing if the types in "ExampleLayer" depend on any object in "ForbiddenLayer"
[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);
}
Testing naming of classes implementing "ForbiddenInterfaces"
[Fact]
public void ForbiddenClassesShouldHaveCorrectName()
{
Classes().That().AreAssignableTo(ForbiddenInterfaces)
.Should().HaveNameContaining("forbidden").Check(Architecture);
}
Testing if "ExampleClasses" call any method declared in "ForbiddenLayer" or with name containing "forbidden"
[Fact]
public void ExampleClassesShouldNotCallForbiddenMethods()
{
Classes().That().Are(ExampleClasses).Should()
.NotCallAny(MethodMembers().That()
.AreDeclaredIn(ForbiddenLayer).Or().HaveNameContaining("forbidden"))
.Check(Architecture);
}
3. What to Check
The following section illustrates some typical checks you could do with ArchUnitNET.
Find this example code here.
3.1. Namespace Dependency Rule
IArchRule rule = Types().That().ResideInNamespace("Model").Should()
.NotDependOnAny(Types().That().ResideInNamespace("Controller"));
3.2. Class Dependency Rule
IArchRule rule = Classes().That().AreAssignableTo(typeof(ICar)).Should()
.NotDependOnAny(Classes().That().AreAssignableTo(typeof(ICanvas)));
3.3. Inheritance Naming Rule
IArchRule rule = Classes().That().AreAssignableTo(typeof(ICar)).Should()
.HaveNameContaining("Car");
3.4. Class Namespace Containment Rule
IArchRule rule = Classes().That().HaveNameContaining("Canvas").Should()
.ResideInNamespace(typeof(ICanvas).Namespace);
3.5. Attribute Access Rule
IArchRule rule = Classes().That().DoNotHaveAnyAttributes(typeof(Display)).Should()
.NotDependOnAny(Classes().That().AreAssignableTo(typeof(ICanvas)));
3.6. Cycle Rule
IArchRule rule = Slices().Matching("Module.(*)").Should()
.BeFreeOfCycles();
4. How to check
To get a meaningful error message we recommend using the xUnit or NUnit extension.
4.1 ArchUnitNET xUnit/NUnit extension
IArchRule someRule = ...;
someRule.check(Architecture);
4.2 ArchUnitNET no extension
IArchRule someRule = ...;
bool checkedRule = someRule.HasNoViolations(Architecture);
Assert.True(checkedRule);
5. Further Reading and Examples
A complete overview of all available methods can be found here.
Check out example code on Github.