📋 Story
As a developer using AwsLambda.Host, I want to write integration tests for my Lambda functions that test the full request/response cycle including middleware, similar to how WebApplicationFactory works in ASP.NET Core.
🎯 Goals
Create a new package AwsLambda.Host.Testing that:
- Follows the WebApplicationFactory pattern from ASP.NET Core
- Enables bootstrap-level testing by mocking the Lambda Runtime API
- Supports invoking test events and capturing responses
- Allows service overrides for testing scenarios
- Explicitly supports testing custom middleware
💡 Design Approach
Core Architecture
The package will leverage the existing LambdaHostOptions.BootstrapHttpClient property to inject a custom HttpMessageHandler that mocks the AWS Lambda Runtime API HTTP endpoints:
GET /runtime/invocation/next - Returns queued test events
POST /runtime/invocation/{requestId}/response - Captures success responses
POST /runtime/invocation/{requestId}/error - Captures error responses
Key Components
-
LambdaApplicationFactory<TProgram> - Main factory class
- Generic parameter for program/entry point discovery
- Virtual
ConfigureServices() for service overrides
- Virtual
ConfigureApplication() for builder customization
- Implements
IAsyncDisposable for lifecycle management
-
MockLambdaRuntimeApiHandler - Internal HTTP message handler
- In-memory queue for test events (using
System.Threading.Channels)
- Captures responses using
TaskCompletionSource
- No external HTTP server needed
-
InvocationResult / InvocationResult<TResponse> - Result wrappers
- Success/error status
- Raw JSON responses
- Typed response deserialization
- Duration tracking
- Lambda context reference
Public API Design
// Basic usage
public class LambdaTests : IAsyncDisposable
{
private readonly LambdaApplicationFactory<Program> _factory = new();
[Fact]
public async Task Handler_ReturnsExpectedResponse()
{
var result = await _factory.InvokeAsync<MyRequest, MyResponse>(
new MyRequest { Name = "Test" }
);
result.IsSuccess.Should().BeTrue();
result.Response!.Message.Should().Be("Hello Test");
}
public ValueTask DisposeAsync() => _factory.DisposeAsync();
}
// With service overrides
public class CustomFactory : LambdaApplicationFactory<Program>
{
protected override void ConfigureServices(IServiceCollection services)
{
services.Replace(ServiceDescriptor.Singleton<IMyService, MockService>());
}
}
// Raw JSON support
var result = await factory.InvokeAsync("""{"name": "Test"}""");
Invocation Methods
The factory will provide multiple invocation overloads:
InvokeAsync<TEvent, TResponse>(TEvent event) - Typed request and response
InvokeAsync<TEvent>(TEvent event) - Typed request, no response
InvokeAsync(string eventJson) - Raw JSON input
📦 Package Structure
src/AwsLambda.Host.Testing/
├── AwsLambda.Host.Testing.csproj
├── LambdaApplicationFactory.cs
├── Runtime/
│ ├── MockLambdaRuntimeApiHandler.cs
│ ├── MockInvocation.cs
│ └── InvocationResult.cs
└── Extensions/
└── ServiceCollectionExtensions.cs (if needed)
tests/AwsLambda.Host.Testing.UnitTests/
└── LambdaApplicationFactoryTests.cs
✅ Acceptance Criteria
🔍 Technical Notes
Integration Points
LambdaHostOptions.BootstrapHttpClient - Already exists (line 14 in LambdaHostOptions.cs), provides the injection point for test HTTP client
LambdaBootstrapAdapter - Already supports custom HttpClient (lines 35-42 in LambdaBootstrapAdapter.cs)
ILambdaSerializer - Use existing serializer from DI for event/response serialization
Key Files to Reference
/src/AwsLambda.Host/Runtime/LambdaBootstrapAdapter.cs - Bootstrap integration
/src/AwsLambda.Host/Core/Options/LambdaHostOptions.cs - Options pattern
/src/AwsLambda.Host/Builder/LambdaApplicationBuilder.cs - Builder pattern
/src/AwsLambda.Host/Runtime/LambdaHandlerComposer.cs - Handler pipeline composition
/tests/AwsLambda.Host.UnitTests/Builder/LambdaApplicationBuilderTests.cs - Testing patterns
Design Decisions
- Minimal Scope: Only provide the factory infrastructure - users bring their own assertion libraries (FluentAssertions, Shouldly, etc.)
- Bootstrap Level: Test the full lifecycle including init/shutdown handlers, not just the handler pipeline
- Raw JSON Support: Prioritize raw JSON input with generic serialization helper
- Middleware Support: Explicitly design for testing custom middleware
🎨 Future Enhancements (Not in Scope)
- Assertion helpers for Lambda responses
- Built-in mock
ILambdaContext with fluent configuration
- Support for concurrent invocations
- Explicit init/shutdown testing APIs
📚 References
📋 Story
As a developer using AwsLambda.Host, I want to write integration tests for my Lambda functions that test the full request/response cycle including middleware, similar to how WebApplicationFactory works in ASP.NET Core.
🎯 Goals
Create a new package
AwsLambda.Host.Testingthat:💡 Design Approach
Core Architecture
The package will leverage the existing
LambdaHostOptions.BootstrapHttpClientproperty to inject a customHttpMessageHandlerthat mocks the AWS Lambda Runtime API HTTP endpoints:GET /runtime/invocation/next- Returns queued test eventsPOST /runtime/invocation/{requestId}/response- Captures success responsesPOST /runtime/invocation/{requestId}/error- Captures error responsesKey Components
LambdaApplicationFactory<TProgram>- Main factory classConfigureServices()for service overridesConfigureApplication()for builder customizationIAsyncDisposablefor lifecycle managementMockLambdaRuntimeApiHandler- Internal HTTP message handlerSystem.Threading.Channels)TaskCompletionSourceInvocationResult/InvocationResult<TResponse>- Result wrappersPublic API Design
Invocation Methods
The factory will provide multiple invocation overloads:
InvokeAsync<TEvent, TResponse>(TEvent event)- Typed request and responseInvokeAsync<TEvent>(TEvent event)- Typed request, no responseInvokeAsync(string eventJson)- Raw JSON input📦 Package Structure
✅ Acceptance Criteria
ConfigureServices()🔍 Technical Notes
Integration Points
LambdaHostOptions.BootstrapHttpClient- Already exists (line 14 inLambdaHostOptions.cs), provides the injection point for test HTTP clientLambdaBootstrapAdapter- Already supports custom HttpClient (lines 35-42 inLambdaBootstrapAdapter.cs)ILambdaSerializer- Use existing serializer from DI for event/response serializationKey Files to Reference
/src/AwsLambda.Host/Runtime/LambdaBootstrapAdapter.cs- Bootstrap integration/src/AwsLambda.Host/Core/Options/LambdaHostOptions.cs- Options pattern/src/AwsLambda.Host/Builder/LambdaApplicationBuilder.cs- Builder pattern/src/AwsLambda.Host/Runtime/LambdaHandlerComposer.cs- Handler pipeline composition/tests/AwsLambda.Host.UnitTests/Builder/LambdaApplicationBuilderTests.cs- Testing patternsDesign Decisions
🎨 Future Enhancements (Not in Scope)
ILambdaContextwith fluent configuration📚 References