Skip to main content

Feature Comparison with FluentAssertions

This document provides a comprehensive comparison between aweXpect.Reflection and FluentAssertions for reflection-based testing scenarios. Both libraries offer powerful capabilities for asserting against reflection types, but with different syntax patterns and feature sets.

Overview

aweXpect.Reflection is designed as an extension to the aweXpect testing framework, providing expectations for reflection types with async/await support and rich filtering capabilities.

FluentAssertions is a popular general-purpose assertion library that includes extensive reflection testing features alongside other assertion types.

Feature Comparison Matrix

Feature CategoryaweXpect.ReflectionFluentAssertionsNotes
Assembly TestingBoth support assembly-level assertions
Type TestingBoth support comprehensive type assertions
Method TestingBoth support method-level assertions
Property TestingBoth support property assertions
Field TestingBoth support field assertions
Event TestingBoth support event assertions
Constructor TestingBoth support constructor assertions
Attribute TestingBoth support attribute presence/value testing
Collection Filtering⚠️aweXpect has more advanced filtering via In

| String Matching Options | ✅ | ✅ | Both support prefix, suffix, regex, wildcards | | Dependency Testing | ✅ | ✅ | Both support assembly dependency checks | | Access Modifier Testing | ✅ | ✅ | Both support public/private/protected/internal | | Type Kind Testing | ✅ | ✅ | Both support class/interface/enum/abstract/etc |

Detailed Feature Breakdown

1. Assembly Assertions

aweXpect.Reflection

// Single assembly
await Expect.That(assembly).HasName("MyAssembly");
await Expect.That(assembly).HasADependencyOn("System.Core");
await Expect.That(assembly).HasNoDependencyOn("UnwantedDependency");

// Multiple assemblies
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
await Expect.That(assemblies).HaveName("System").AsPrefix();

FluentAssertions

// Single assembly
assembly.Should().HaveAssemblyName("MyAssembly");
assembly.Should().Reference("System.Core");
assembly.Should().NotReference("UnwantedDependency");

// Multiple assemblies - requires more manual work
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
assemblies.Should().OnlyContain(a => a.FullName.StartsWith("System"));

2. Type Assertions

aweXpect.Reflection

// Single type
await Expect.That(typeof(MyClass)).IsAClass();
await Expect.That(typeof(IMyInterface)).IsAnInterface();
await Expect.That(typeof(MyEnum)).IsAnEnum();
await Expect.That(typeof(AbstractClass)).IsAbstract();
await Expect.That(typeof(MyClass)).HasNamespace("MyNamespace");
await Expect.That(typeof(MyClass)).Has<MyAttribute>();

// Multiple types with advanced filtering
await Expect.That(In.AllLoadedAssemblies()
.Types().WhichAreClasses().WhichArePublic())
.HaveNamespace("MyNamespace").AsPrefix();

FluentAssertions

// Single type
typeof(MyClass).Should().BeClass();
typeof(MyInterface).Should().BeInterface();
typeof(MyEnum).Should().BeEnum();
typeof(AbstractClass).Should().BeAbstract();
typeof(MyClass).Should().BeInNamespace("MyNamespace");
typeof(MyClass).Should().BeDecoratedWith<MyAttribute>();

// Multiple types
var types = Assembly.GetExecutingAssembly().GetTypes();
types.Should().OnlyContain(t => t.IsClass && t.IsPublic);

3. Method Assertions

aweXpect.Reflection

// Single method
MethodInfo method = typeof(MyClass).GetMethod("MyMethod");
await Expect.That(method).IsPublic();
await Expect.That(method).HasName("MyMethod");
await Expect.That(method).Has<ObsoleteAttribute>();

// Multiple methods with filtering
await Expect.That(In.AssemblyContaining<MyClass>()
.Methods().WhichArePublic().With<TestAttribute>())
.HaveName("Test").AsPrefix();

FluentAssertions

// Single method
MethodInfo method = typeof(MyClass).GetMethod("MyMethod");
method.Should().BePublic();
method.Should().HaveName("MyMethod");
method.Should().BeDecoratedWith<ObsoleteAttribute>();

// Multiple methods
var methods = typeof(MyClass).GetMethods();
methods.Should().OnlyContain(m => m.IsPublic);

4. Property Assertions

aweXpect.Reflection

// Single property
PropertyInfo property = typeof(MyClass).GetProperty("MyProperty");
await Expect.That(property).IsPublic();
await Expect.That(property).HasName("MyProperty");

// Multiple properties
await Expect.That(In.AssemblyContaining<MyClass>()
.Properties().WhichArePublic())
.HaveName("Id").AsSuffix();

FluentAssertions

// Single property
PropertyInfo property = typeof(MyClass).GetProperty("MyProperty");
property.Should().BePublic();
property.Should().HaveName("MyProperty");

// Multiple properties
var properties = typeof(MyClass).GetProperties();
properties.Should().OnlyContain(p => p.GetGetMethod().IsPublic);

5. Advanced Filtering and Collection Operations

aweXpect.Reflection

// Complex filtering scenarios
await Expect.That(In.AllLoadedAssemblies()
.Methods().With<FactAttribute>().OrWith<TheoryAttribute>()
.DeclaringTypes())
.HaveName("Tests").AsSuffix();

// Filter by return types
await Expect.That(In.AssemblyContaining(typeof(In))
.Methods().WhichReturn<Task>().OrReturn<ValueTask>())
.HaveName("Async").AsSuffix();

FluentAssertions

// Requires more manual LINQ operations
var testClasses = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.Where(t => t.GetMethods()
.Any(m => m.HasAttribute<FactAttribute>() || m.HasAttribute<TheoryAttribute>()));

testClasses.Should().OnlyContain(t => t.Name.EndsWith("Tests"));

// Return type filtering requires manual work
var methods = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes().SelectMany(t => t.GetMethods()))
.Where(m => m.ReturnType == typeof(Task) || m.ReturnType == typeof(ValueTask));
methods.Should().OnlyContain(m => m.Name.EndsWith("Async"));