Use when AWS Lambda functions with API Gateway need testing locally: sam local invoke with event payloads, start-api for a local API Gateway, start-lambda for SDK clients and generate-event, plus .NET Lambda handler tests with Amazon.Lambda.TestUtilities.
89%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
For C#/.NET Lambdas the fast path is handler-direct invocation with a
mock context, not spawning sam local invoke per test. AWS's canonical
toolkit is aws-lambda-dotnet:
Amazon.Lambda.TestUtilities for library-level fakes plus the
Mock Lambda Test Tool
UI for manual invocation.
dotnet add package Amazon.Lambda.Core
dotnet add package Amazon.Lambda.Serialization.SystemTextJson
dotnet add package Amazon.Lambda.TestUtilities
dotnet add package Microsoft.NET.Test.Sdk
dotnet add package xunitPer Amazon.Lambda.TestUtilities:
using Amazon.Lambda.Core;
using Amazon.Lambda.Serialization.SystemTextJson;
[assembly: LambdaSerializer(typeof(DefaultLambdaJsonSerializer))]
public class Functions
{
public string Handler(string input, ILambdaContext context)
{
context.Logger.LogLine($"Got input: {input}");
return input.ToUpper();
}
}using Amazon.Lambda.TestUtilities;
using Xunit;
[Fact]
public void Handler_Uppercases()
{
var context = new TestLambdaContext
{
FunctionName = "test-fn",
RemainingTime = TimeSpan.FromSeconds(30), // Logger auto-set to TestLambdaLogger
};
Assert.Equal("HELLO", new Functions().Handler("hello", context));
}
[Fact]
public void Handler_LogsInput()
{
var context = new TestLambdaContext();
new Functions().Handler("hi", context);
var logger = (TestLambdaLogger)context.Logger;
Assert.Contains("Got input: hi", logger.Buffer.ToString());
}Set RemainingTime low to exercise timeout-aware handlers (the
early-return pattern in the timeout-budgets reference of
serverless-integration-test-builder):
var context = new TestLambdaContext { RemainingTime = TimeSpan.FromSeconds(3) };
var result = new Functions().Handler("work-that-takes-time", context);
Assert.Contains("partial", result);var json = File.ReadAllText("Events/apigw-request.json"); // from sam local generate-event
var request = new DefaultLambdaJsonSerializer().Deserialize<APIGatewayProxyRequest>(json);
var response = new Functions().HandleApi(request, new TestLambdaContext());
Assert.Equal(200, response.StatusCode);Per aws-extensions-for-dotnet-cli:
dotnet tool install -g Amazon.Lambda.Tools
dotnet lambda invoke-function MyFunction --payload '"hello"'For local-only testing, prefer handler-direct invocation.
jobs:
dotnet-lambda-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-dotnet@v4
with: { dotnet-version: '8.0.x' }
- run: dotnet restore
- run: dotnet test --no-build --verbosity normal| Anti-pattern | Why it fails | Fix |
|---|---|---|
Spawn dotnet lambda invoke per test | Network calls; slow; rate-limited | Handler-direct invocation |
Skip TestLambdaContext | Null context fails at runtime | Always pass one |
RemainingTime = TimeSpan.MaxValue | Timeout logic never exercised | Realistic remaining time |
Hand-rolled APIGatewayProxyRequest | Schema drift | sam local generate-event fixture |
Missing [assembly: LambdaSerializer] | Runtime deserialization fails | Register the serializer in tests too |
| Mocking the Logger | Loses TestLambdaLogger.Buffer replay | Use the default TestLambdaContext logger |
next/response polling) is not exercised.