From qa-serverless
Wraps Amazon.Lambda.TestTool (the canonical .NET Lambda local-testing toolkit from github.com/aws/aws-lambda-dotnet) for invoking Lambda handlers from xUnit / NUnit tests with simulated AWS Lambda contexts (ILambdaContext, ILambdaSerializer). Covers handler-direct invocation, mock context fixtures, the dotnet-lambda CLI, and integration with the .NET LambdaSerializer for JSON. Use when testing AWS Lambda functions written in C#/.NET. Composes cold-start-budget-reference + lambda-timeout-budget-reference.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qa-serverless:lambda-test-tools-netThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
`Amazon.Lambda.TestTool` is AWS's canonical .NET package for
Amazon.Lambda.TestTool is AWS's canonical .NET package for
testing Lambda functions. Per
github.com/aws/aws-lambda-dotnet,
it provides a Mock Lambda Test Tool (Windows / Mac / Linux UI to
manually invoke Lambdas) plus library-level fakes for
ILambdaContext.
For automated tests, the pattern is handler-direct invocation with a mock context.
dotnet lambda invoke per test.dotnet add package Amazon.Lambda.Core
dotnet add package Amazon.Lambda.Serialization.SystemTextJson
dotnet add package Amazon.Lambda.TestUtilities # NUnit-friendly mocks
dotnet add package Microsoft.NET.Test.Sdk
dotnet add package xunit
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();
}
}
Per aws-lambda-dotnet Amazon.Lambda.TestUtilities:
using Amazon.Lambda.TestUtilities;
using Xunit;
public class FunctionsTests
{
[Fact]
public void Handler_Uppercases()
{
var functions = new Functions();
var context = new TestLambdaContext
{
FunctionName = "test-fn",
RemainingTime = TimeSpan.FromSeconds(30),
// Logger is auto-set to TestLambdaLogger
};
var result = functions.Handler("hello", context);
Assert.Equal("HELLO", result);
}
[Fact]
public void Handler_LogsInput()
{
var functions = new Functions();
var context = new TestLambdaContext();
functions.Handler("hi", context);
var logger = (TestLambdaLogger)context.Logger;
Assert.Contains("Got input: hi", logger.Buffer.ToString());
}
}
Per lambda-timeout-budget-reference,
handlers that check Context.RemainingTime:
[Fact]
public void Handler_EarlyReturnsWhenTimeLow()
{
var functions = new Functions();
var context = new TestLambdaContext
{
RemainingTime = TimeSpan.FromSeconds(3) // Below 5s threshold
};
var result = functions.Handler("work-that-takes-time", context);
Assert.Contains("partial", result);
}
[Fact]
public void Handler_ParsesApiGatewayEvent()
{
var json = File.ReadAllText("Events/apigw-request.json");
var serializer = new DefaultLambdaJsonSerializer();
var request = serializer.Deserialize<APIGatewayProxyRequest>(json);
var functions = new Functions();
var response = functions.HandleApi(request, new TestLambdaContext());
Assert.Equal(200, response.StatusCode);
}
Per github.com/aws/aws-extensions-for-dotnet-cli:
dotnet tool install -g Amazon.Lambda.Tools
dotnet lambda invoke-function MyFunction --payload '"hello"'
For local-only testing, prefer the handler-direct pattern above.
dotnet test
For watch-mode:
dotnet watch test
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 | Real ILambdaContext is required; null fails | Always pass a context |
RemainingTime = TimeSpan.MaxValue | Doesn't exercise timeout logic | Set realistic remaining time |
| Hand-rolled APIGatewayProxyRequest | Schema drift | Generate via sam local generate-event or commit fixture |
| Test using prod IAM | Permissions surprise in CI | Use mock service clients |
| No assertion on logger output | Logger bugs slip through | Inspect TestLambdaLogger.Buffer |
| Serializer not registered | LambdaSerializer attribute missing → runtime fails | Add assembly attribute |
| Mocking the Logger | Loses TestLambdaLogger's buffer-replay capability | Use TestLambdaContext's default logger |
next / response polling) isn't invoked;
bugs in handler-vs-runtime contract slip through.cold-start-budget-reference.
In-process tests are warm; AOT cold-start savings invisible.cold-start-budget-reference,
lambda-timeout-budget-reference.aws-sam-local-testing
(Node/Python/Java equivalent).Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub testland/qa --plugin qa-serverless