This project validates that TUnit is fully compatible with .NET Native AOT (Ahead-of-Time) compilation in source generation mode.
The TUnit framework has been enhanced to support AOT compilation by:
- Replacing reflection-heavy code with source-generated alternatives
- Adding proper
[DynamicallyAccessedMembers]attributions for remaining reflection usage - Implementing AOT-safe type resolution to replace
Type.GetType()andMakeGenericType()calls - Creating source generators for method invocation, property injection, and tuple processing
- Adding comprehensive AOT compatibility analyzers to prevent regressions
- Basic test execution without reflection
- Parameterized tests with source-generated argument processing
- Method and class data sources with generated invocation code
- Generic type handling with compile-time resolution
- Hook execution (Before/After) with generated delegates
- Object comparison with proper member access attribution
- Exception assertions with type-safe checking
- Collection assertions without runtime reflection
- Property-based assertions (with appropriate AOT warnings)
- Complete test discovery at compile time
- Strongly-typed test method invocation
- Property injection with generated setters
- Tuple processing with generated unwrapping code
- Type registry for AOT-safe generic type resolution
- Matrix data sources with complex type combinations
- Async test execution
- Global and assembly-level hooks
- Shared data sources with proper instantiation
- Generic test classes with concrete implementations
This project is configured with:
<PropertyGroup>
<!-- Enable AOT publishing -->
<PublishAot>true</PublishAot>
<InvariantGlobalization>true</InvariantGlobalization>
<!-- Source generation mode -->
<TUNIT_EXECUTION_MODE>SourceGeneration</TUNIT_EXECUTION_MODE>
<!-- Enable all AOT analysis warnings -->
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
<EnableAotAnalyzer>true</EnableAotAnalyzer>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>.\build-aot.ps1# Set environment variable
export TUNIT_EXECUTION_MODE=SourceGeneration
# Clean and build
dotnet clean --configuration Release
dotnet build --configuration Release
# Run tests
dotnet test --configuration Release
# Publish with AOT
dotnet publish --configuration ReleaseWhen running successfully, you should see:
- ✅ Build completes without AOT warnings
- ✅ All tests pass
- ✅ Native executable generated (typically 10-50MB)
- ✅ No reflection usage in published output
The tests validate several key aspects:
- No Runtime Reflection: All type discovery, method invocation, and property access uses compile-time generated code
- Source Generation Active: Verifies that
TUNIT_EXECUTION_MODE=SourceGenerationis working - Type Resolution: Generic types and complex scenarios work without
Type.GetType()orMakeGenericType() - Data Source Processing: Method and class data sources use generated invocation instead of
MethodInfo.Invoke() - Property Injection: Uses generated setters instead of reflection-based property setting
- Tuple Processing: Uses generated unwrapping code instead of field reflection
If AOT compilation fails:
- Check for new reflection usage - The enhanced analyzers should catch this at build time
- Verify source generation mode - Ensure
TUNIT_EXECUTION_MODE=SourceGenerationis set - Review trimming warnings - Look for IL2xxx warnings that indicate reflection issues
- Validate attributions - Ensure all reflection usage has proper
[DynamicallyAccessedMembers]attribution
This test project validates the following source-generated components:
- AotTypeResolverGenerator: Replaces
TypeResolver.cswith compile-time type mapping - AotMethodInvocationGenerator: Generates strongly-typed method delegates
- AotTupleProcessorGenerator: Creates compile-time tuple unwrapping code
- EnhancedPropertyInjectionGenerator: Generates property setters with UnsafeAccessor
- AotModuleInitializerGenerator: Wires all components together automatically
AOT compilation with TUnit provides:
- Faster startup time (no JIT compilation)
- Smaller memory footprint (trimmed assemblies)
- Predictable performance (no runtime code generation)
- Better security (no dynamic code execution)
This project is considered successful when:
- All tests pass ✅
- AOT publish completes without warnings ✅
- Native executable runs successfully ✅
- No reflection usage in critical paths ✅
- Source generation provides complete coverage ✅