aweXpect.Reflection
4.0.0-pre.3
Prefix Reserved
dotnet add package aweXpect.Reflection --version 4.0.0-pre.3
NuGet\Install-Package aweXpect.Reflection -Version 4.0.0-pre.3
<PackageReference Include="aweXpect.Reflection" Version="4.0.0-pre.3" />
<PackageVersion Include="aweXpect.Reflection" Version="4.0.0-pre.3" />
<PackageReference Include="aweXpect.Reflection" />
paket add aweXpect.Reflection --version 4.0.0-pre.3
#r "nuget: aweXpect.Reflection, 4.0.0-pre.3"
#:package aweXpect.Reflection@4.0.0-pre.3
#addin nuget:?package=aweXpect.Reflection&version=4.0.0-pre.3&prerelease
#tool nuget:?package=aweXpect.Reflection&version=4.0.0-pre.3&prerelease
aweXpect.Reflection
aweXpect.Reflection contains expectations for reflection types.
Installation
dotnet add package aweXpect.Reflection
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;.
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 Expect.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 | Expect.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 Expect.That(In.AllLoadedAssemblies()
.Public.Classes()
.WhichContainMethods(m => m.With<FactAttribute>().OrWith<TheoryAttribute>()))
.HaveName("Tests").AsSuffix();
// Verify all async methods have an "Async" suffix
await Expect.That(In.AssemblyContaining<PlaylistService>()
.Methods().WhichAreAsync())
.HaveName("Async").AsSuffix();
// Verify all methods with an "Async" suffix return Task or ValueTask
await Expect.That(In.AssemblyContaining<PlaylistService>()
.Methods().WithName("Async").AsSuffix())
.Return<Task>().OrReturn<ValueTask>();
// Verify controllers follow the naming convention
await Expect.That(In.AllLoadedAssemblies()
.Types().WhichInheritFrom<ControllerBase>())
.HaveName("Controller").AsSuffix();
// Verify each event handler is named after the event it handles (e.g. "OnTrackAdded")
await Expect.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 Expect.That(In.AllLoadedAssemblies()
.Types().With<SerializableAttribute>())
.ContainConstructors(c => c.WithNoParameters()).Exactly(1);
Overview
Each filter narrows a selection and its expectation counterpart verifies it, e.g. .WhichArePublic() and
.IsPublic() (.ArePublic() for collections):
- Common filters: access modifiers, attributes, the obsolete marker, names and
namespaces of types and members, e.g.
WhichArePublic/IsPublicorWith<TAttribute>/Has<TAttribute> - Assemblies: name, target framework, version, strong name and dependencies, e.g.
WhichTarget/TargetsorWhichDependOn/DependsOn - Types and inheritance: kinds of types, base classes, interfaces and contained members,
e.g.
WhichAreClasses/IsAClassorWhichInheritFrom<T>/InheritsFrom<T>, and how inherited members count - Methods, operators and constructors: return types and parameters, e.g.
WhichAreAsync/IsAsync,WhichReturn<T>/Returns<T>orWithParameter<T>/HasParameter<T> - Properties, fields and events: member types, nullability and
accessors, e.g.
WhichAreOfType<T>/IsOfType<T>orWhichAreRequired/IsRequired
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.
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(
Expect.That(domainTypes).DoNotDependOn(infrastructureTypes),
Expect.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.
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.3)
-
net10.0
- aweXpect.Core (>= 4.0.0-pre.3)
-
net8.0
- aweXpect.Core (>= 4.0.0-pre.3)
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.3 | 66 | 10/29/2026 |
| 4.0.0-pre.2 | 48 | 10/27/2026 |
| 4.0.0-pre.1 | 54 | 10/22/2026 |
| 3.1.0 | 855 | 10/16/2026 |
| 3.0.0 | 314 | 10/10/2026 |
| 3.0.0-pre.2 | 56 | 10/8/2026 |
| 3.0.0-pre.1 | 70 | 9/28/2026 |
| 2.1.0 | 247 | 9/5/2026 |
| 2.0.0 | 982 | 6/7/2026 |
| 2.0.0-pre.2 | 101 | 6/6/2026 |
| 2.0.0-pre.1 | 95 | 6/4/2026 |
| 1.6.0 | 144 | 6/3/2026 |
| 1.5.0 | 147 | 5/31/2026 |
| 1.4.0 | 135 | 5/30/2026 |
| 1.3.0 | 134 | 5/28/2026 |
| 1.2.0 | 134 | 5/27/2026 |
| 1.1.0 | 140 | 5/10/2026 |
| 1.0.0 | 324 | 9/19/2025 |
| 0.7.0 | 234 | 9/11/2025 |
| 0.6.0 | 247 | 8/17/2025 |