Testland
Browse all skills & agents

lambda-test-tools-net

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.

Install with skills.sh (any agent)

npx skills add testland/qa --skill lambda-test-tools-net
View source

lambda-test-tools-net

Overview

Amazon.Lambda.TestTool is AWS's canonical .NET package for testing Lambda functions. Per github.com/aws/aws-lambda-dotnet (opens in new window), 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.

When to use

  • xUnit / NUnit tests for .NET Lambda handlers.
  • Verifying handler logic without spinning up dotnet lambda invoke per test.
  • CI integration with deterministic, fast tests.

Authoring

Install

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

Handler example

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();
    }
}

Test with TestLambdaContext

Per aws-lambda-dotnet Amazon.Lambda.TestUtilities (opens in new window):

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());
    }
}

Testing remaining-time behaviour

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);
}

Test with serialised event payloads

[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);
}

dotnet-lambda CLI (for the deploy + invoke path)

Per github.com/aws/aws-extensions-for-dotnet-cli (opens in new window):

dotnet tool install -g Amazon.Lambda.Tools

dotnet lambda invoke-function MyFunction --payload '"hello"'

For local-only testing, prefer the handler-direct pattern above.

Running

dotnet test

For watch-mode:

dotnet watch test

CI integration

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-patterns

Anti-patternWhy it failsFix
Spawn dotnet lambda invoke per testNetwork calls; slow; rate-limitedHandler-direct invocation
Skip TestLambdaContextReal ILambdaContext is required; null failsAlways pass a context
RemainingTime = TimeSpan.MaxValueDoesn't exercise timeout logicSet realistic remaining time
Hand-rolled APIGatewayProxyRequestSchema driftGenerate via sam local generate-event or commit fixture
Test using prod IAMPermissions surprise in CIUse mock service clients
No assertion on logger outputLogger bugs slip throughInspect TestLambdaLogger.Buffer
Serializer not registeredLambdaSerializer attribute missing → runtime failsAdd assembly attribute
Mocking the LoggerLoses TestLambdaLogger's buffer-replay capabilityUse TestLambdaContext's default logger

Limitations

  • No JIT / native AoT difference. Local handler invocation uses standard .NET JIT; AOT-compiled Lambdas (ReadyToRun / Native AOT) behave differently. Pair with deployed-Lambda tests for production representativeness.
  • Doesn't test the runtime API. The Lambda runtime API (responsible for next / response polling) isn't invoked; bugs in handler-vs-runtime contract slip through.
  • Doesn't test cold-start budget per cold-start-budget-reference. In-process tests are warm; AOT cold-start savings invisible.
  • Custom serializer paths. If your handler uses a non-default JSON serializer, set up the assembly attribute identically in tests.

References

Related skills

aws-sam-local-testing

Wraps AWS SAM (Serverless Application Model) Local CLI for testing Lambda functions locally: `sam local invoke` (single invocation with event payload), `sam local start-api` (local API Gateway emulator), `sam local start-lambda` (local Lambda invoke endpoint for AWS SDK clients), and event-payload generation (`sam local generate-event`). Use when testing Lambda + API Gateway + integrated AWS services locally.

azure-functions-tests

Runs Azure Functions locally using Azure Functions Core Tools v4 (`func start`), Azurite storage emulation, and framework-native unit tests for handler code (.NET isolated worker model, Node.js v4, Python v2). Covers HTTP, queue, and timer trigger testing, admin-endpoint invocation for non-HTTP triggers, and binding verification via local.settings.json. Use when testing Azure Functions before deployment, reproducing trigger behaviour without live Azure services, or gating function handler logic in CI.

cloudflare-workers-miniflare

Wraps Miniflare 3 (the official Cloudflare Workers simulator) and Wrangler dev for testing Workers locally. Covers Miniflare's getMiniflare() programmatic API (workerd-backed simulation matching prod), the wrangler dev local-mode (live-reload during dev), KV / Durable Objects / R2 / D1 bindings emulation, and Vitest + @cloudflare/vitest-pool-workers for in-process tests. Use when testing Cloudflare Workers code locally.

cold-start-budget-reference

Pure-reference catalog of cold-start budgets across serverless runtimes. Covers AWS Lambda's three-phase cold start (Init: download+unzip+runtime-bootstrap; Init code: imports + module load; Invoke: handler execution), Cloudflare Workers' isolate model (sub-millisecond cold starts via V8 isolates per developers.cloudflare.com), Vercel Edge Runtime, Lambda SnapStart for JVM (snapshot-restore for Java), and provisioned-concurrency trade-offs. Includes per-runtime typical cold-start ranges and the testable behaviours each model creates. Use when designing latency budgets, choosing a runtime, or auditing cold-start variance in production.

lambda-timeout-budget-reference

Pure-reference catalog of AWS Lambda timeout + billing semantics. Covers Lambda's hard 15-minute (900s) wall-clock limit, the timeout-vs-deadline relationship (Lambda Context.getRemainingTimeInMillis), per-invocation billing (rounded to 1ms; per-invocation + duration × memory), the memory-vs-CPU relationship (CPU scales linearly with memory), the integration-timeout cascade (API Gateway 29s → Lambda 15min; SQS visibility-timeout vs Lambda timeout), and per-runtime nuances. Use when designing a Lambda's timeout config, debugging timeout-vs-billing surprises, or sizing memory for compute-bound workloads.

netlify-functions-tests

Wraps Netlify Functions testing patterns: Netlify Dev (`netlify dev`) for local routing emulation, the @netlify/functions handler API testing pattern, Netlify Edge Functions (Deno runtime) vs Background Functions (Lambda under the hood) distinction, and scheduled-function (cron) test patterns. Use when testing Netlify Functions or Edge Functions.

serverless-framework-test-plugin

Wraps the Serverless Framework (serverless.com) test ecosystem: serverless-offline (local HTTP emulator), serverless-jest-plugin / serverless-mocha-plugin (per-runtime test runners), and the `serverless invoke local` CLI for one-off invocations. Use when testing Lambda functions deployed via the Serverless Framework.

serverless-integration-test-builder

Workflow-driven skill that builds the integration-test suite for a serverless application from its IaC definition (SAM template / serverless.yml / Wrangler config / Vercel functions / Netlify functions). Walks through: identifying the function inventory + event sources, picking the right local-emulator per function (sam local / Miniflare / netlify dev / vercel dev / serverless-offline), generating test events per event source, asserting on cold-start + timeout budgets, and emitting the test directory + CI config. Use when introducing integration tests to a serverless project.

vercel-edge-runtime-testing

Wraps Vercel Edge Runtime testing patterns: the @edge-runtime/jest-environment + edge-runtime CLI for executing Web-Standard APIs (Request / Response / fetch) in jest tests, the `vercel dev` local emulator for full route testing, and the Edge vs Node Function divergence (no fs, no Buffer; Request / Response only). Covers the 30s Edge function timeout per vercel.com/docs. Use when testing Vercel Edge Functions or middleware.