aweXpect.Reflection
4.0.0-pre.4
Prefix Reserved
dotnet add package aweXpect.Reflection --version 4.0.0-pre.4
NuGet\Install-Package aweXpect.Reflection -Version 4.0.0-pre.4
<PackageReference Include="aweXpect.Reflection" Version="4.0.0-pre.4" />
<PackageVersion Include="aweXpect.Reflection" Version="4.0.0-pre.4" />
<PackageReference Include="aweXpect.Reflection" />
paket add aweXpect.Reflection --version 4.0.0-pre.4
#r "nuget: aweXpect.Reflection, 4.0.0-pre.4"
#:package aweXpect.Reflection@4.0.0-pre.4
#addin nuget:?package=aweXpect.Reflection&version=4.0.0-pre.4&prerelease
#tool nuget:?package=aweXpect.Reflection&version=4.0.0-pre.4&prerelease
aweXpect.Reflection
aweXpect.Reflection extends aweXpect with expectations for reflection types, so you can write architecture and convention tests for assemblies, types and members.
Installation
dotnet add package aweXpect.Reflection --prerelease
The package brings Expect.That with it, but not the expectations for strings, numbers or collections, so reference
aweXpect as well. The expectations live in the namespace aweXpect; the
sources In and Types, their filters and the
customization need
using aweXpect.Reflection;, and a stored selection like Filtered.Types needs
using aweXpect.Reflection.Collections;.
The examples write That(...) instead of Expect.That(...), which needs using static aweXpect.Expect; (see Getting started).
At a glance
Write architecture and convention tests as plain, readable expectations: select the assemblies, types
or members you care about with In or Types, then expect a rule on them with Expect.That.
// "Every async method must end in 'Async'"
await That(In.AssemblyContaining<PlaylistService>() // ① pick a source
.Methods() // ② navigate to a member kind
.WhichAreAsync()) // ③ filter it down
.HaveName("Async").AsSuffix(); // ④ expect
Every expectation follows the same four-part shape:
| Step | What it does | Examples |
|---|---|---|
| ① Source | choose where to look | In.AllLoadedAssemblies(), In.AssemblyContaining<T>(), In.Type<T>() |
| ② Navigate | move to a member kind | .Types(), .Methods(), .Properties(), .Fields(), .Events(), .Constructors() |
| ③ Filter (optional) | narrow the set | .WhichArePublic(), .With<T>(), .WithName(…), .Which(…) |
| ④ Expect | state the rule | That(…).HaveName(…), .AreClasses(), .Return<Task>() |
Steps ② and ③ are optional. You can verify a single Type, MethodInfo, … or a whole Assembly
directly, and every expectation works the same whether the subject is one item or a collection
(Assembly[], IEnumerable<Type?>, …).
The supported reflection subjects are
Assembly,
Type,
ConstructorInfo,
EventInfo,
FieldInfo,
MethodInfo and
PropertyInfo.
Real-world examples
// Verify all test classes (those containing a [Fact] or [Theory] method) follow the naming convention
await That(In.AllLoadedAssemblies()
.Public.Classes()
.WhichContainMethods(m => m.With<FactAttribute>().OrWith<TheoryAttribute>()))
.HaveName("Tests").AsSuffix();
// Verify all async methods have an "Async" suffix
await That(In.AssemblyContaining<PlaylistService>()
.Methods().WhichAreAsync())
.HaveName("Async").AsSuffix();
// Verify all methods with an "Async" suffix return Task or ValueTask
await That(In.AssemblyContaining<PlaylistService>()
.Methods().WithName("Async").AsSuffix())
.Return<Task>().OrReturn<ValueTask>();
// Verify controllers follow the naming convention
await That(In.AllLoadedAssemblies()
.Types().WhichInheritFrom<ControllerBase>())
.HaveName("Controller").AsSuffix();
// Verify each event handler is named after the event it handles (e.g. "OnTrackAdded")
await That(In.AssemblyContaining<Playlist>()
.Methods().Which(m => m.GetParameters().Length == 1))
.HaveName(method => "On" + method.GetParameters()[0].ParameterType.Name);
// Verify each serializable type has exactly one parameterless constructor
await That(In.AllLoadedAssemblies()
.Types().With<SerializableAttribute>())
.ContainConstructors(c => c.WithNoParameters()).Exactly(1);
Architecture rules
There is no separate rule engine: a "layer" is just a reusable type selection, and an architecture rule is
just an expectation on it. Combine several rules into a single verification with Expect.ThatAll:
Filtered.Types domainTypes = Types.InNamespace("MusicStore.Domain");
Filtered.Types infrastructureTypes = Types.InNamespace("MusicStore.Infrastructure");
await Expect.ThatAll(
That(domainTypes).DoNotDependOn(infrastructureTypes),
That(domainTypes).AreSealed());
A failing rule reports all violations, numbered per expectation:
Expected all of the following to succeed:
[01] Expected that types within namespace "MusicStore.Domain" in all loaded assemblies all do not depend on types within namespace "MusicStore.Infrastructure" in all loaded assemblies
[02] Expected that types within namespace "MusicStore.Domain" in all loaded assemblies all are sealed
but
[01] it contained types with the dependency
[02] only 1 of 3 were
[01] Not matching items:
[
PlaylistService
]
[02] Not matching items:
[
Album,
Track
]
[02] Collection:
[
Album,
PlaylistService,
Track
]
The dependency rules (DependOn / DependOnlyOn / HaveDependenciesOutside), dependency cycle detection
(HaveNoDependencyCycles) and exemptions (Except) are documented in
Architecture rules.
Overview
Each filter narrows a selection and its expectation counterpart verifies it, e.g. .WhichArePublic() and
.IsPublic() (.ArePublic() for collections):
| Page | Covers | Examples |
|---|---|---|
| Common filters | access modifiers, attributes, the obsolete marker, names and namespaces of types and members | WhichArePublic / IsPublic, With<TAttribute> / Has<TAttribute> |
| Assemblies | name, target framework, version, strong name and dependencies | WhichTarget / Targets, WhichDependOn / DependsOn |
| Types and inheritance | kinds of types, base classes, interfaces and contained members, and how inherited members count | WhichAreClasses / IsAClass, WhichInheritFrom<T> / InheritsFrom<T> |
| Methods, operators and constructors | return types and parameters | WhichAreAsync / IsAsync, WhichReturn<T> / Returns<T>, WithParameter<T> / HasParameter<T> |
| Properties, fields and events | member types, nullability and accessors | WhichAreOfType<T> / IsOfType<T>, WhichAreRequired / IsRequired |
| Architecture rules | type dependencies, dependency cycles and layers as type selections | DependOn / DependOnlyOn / HaveDependenciesOutside, HaveNoDependencyCycles |
The overview lists all topics,
including combined filters, custom predicates (Which / Satisfies, Except) and quantifiers.
Each filter and expectation has its negation where it makes sense, e.g. WithoutName / DoesNotHaveName,
WithoutNamespace / DoesNotHaveNamespace, WhichAreNotOfType<T> / IsNotOfType<T>, WhichDoNotReturn<T> /
DoesNotReturn<T>, WithoutParameter<T> / DoesNotHaveParameter<T> or WhichDoNotTarget / DoesNotTarget.
On a collection, a negated expectation (DoNotReturn<T>, AreNotOfType<T>, …) verifies that none of the items
match. The tables in
Filters and expectations list every negation in
a Negated column.
The name filters and expectations accept the
string matching options
like AsPrefix(), AsSuffix() or AsWildcard().
Filters and expectations documents the
complete vocabulary.
Customization
Set a value under Customize.aweXpect.Reflection() for the current
async flow, or under
Customize.aweXpect.Global.Reflection() for
all tests.
| Value | Default | Summary |
|---|---|---|
Settings().ExcludedAssemblyPrefixes |
System, Microsoft, … |
assemblies excluded from In.AllLoadedAssemblies() and from DependOnlyOn |
IncludedCompilerGeneratedMembers |
CompilerGeneratedMembers.None |
the compiler-generated types and members included in the navigations |
IncludedSpecialNameMembers |
SpecialNameMembers.None |
the operators and accessors included in .Methods() |
DependencyResolver |
built-in signature-level resolver | how the type-level dependency expectations determine the dependencies of a type |
ExcludedAttributeTypes |
none | additional compiler-emitted attributes that never count as dependencies |
Documentation
The full documentation is available at docs.testably.org:
- Selecting types and members: the
InandTypessources and navigating between assemblies, types and members - Filters and expectations: the complete reference for all subject kinds, string matching options and quantifiers
- Architecture rules: type dependencies, dependency cycles and layers as type selections
- Customization: assembly exclusions, compiler-generated members and the dependency resolver
- Comparisons: feature maps against FluentAssertions and against NetArchTest and ArchUnitNET
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- aweXpect.Core (>= 4.0.0-pre.4)
-
net10.0
- aweXpect.Core (>= 4.0.0-pre.4)
-
net8.0
- aweXpect.Core (>= 4.0.0-pre.4)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.0-pre.4 | 41 | 11/6/2026 |
| 4.0.0-pre.3 | 398 | 10/29/2026 |
| 4.0.0-pre.2 | 61 | 10/27/2026 |
| 4.0.0-pre.1 | 58 | 10/22/2026 |
| 3.1.0 | 878 | 10/16/2026 |
| 3.0.0 | 317 | 10/10/2026 |
| 3.0.0-pre.2 | 58 | 10/8/2026 |
| 3.0.0-pre.1 | 70 | 9/28/2026 |
| 2.1.0 | 249 | 9/5/2026 |
| 2.0.0 | 985 | 6/7/2026 |
| 2.0.0-pre.2 | 107 | 6/6/2026 |
| 2.0.0-pre.1 | 102 | 6/4/2026 |
| 1.6.0 | 150 | 6/3/2026 |
| 1.5.0 | 149 | 5/31/2026 |
| 1.4.0 | 137 | 5/30/2026 |
| 1.3.0 | 136 | 5/28/2026 |
| 1.2.0 | 135 | 5/27/2026 |
| 1.1.0 | 140 | 5/10/2026 |
| 1.0.0 | 325 | 9/19/2025 |
| 0.7.0 | 234 | 9/11/2025 |