Skip to content

LambdaUnitTesting

Dennis Lee edited this page May 21, 2026 · 1 revision

title: Lambda Unit Testing with Mocked AWS Services type: technique created: 2026-05-16 last_updated: 2026-05-16 related: ["Playradar", "radar/techniques/ScriptToProduct"] sources: ["https://aws.amazon.com/blogs/devops/unit-testing-aws-lambda-with-python-and-mock-aws-services/"] radar_quadrant: Techniques radar_ring: Assess radar_position: center

Lambda Unit Testing with Mocked AWS Services

A technique for unit testing AWS Lambda functions in isolation by mocking AWS service calls, enabling fast validation without connecting to real cloud infrastructure. Published by AWS DevOps Blog.

The Problem

Lambda functions that call AWS services (DynamoDB, S3, API Gateway) are difficult to test in isolation. Running tests against real cloud resources is slow, costly, risks touching production data, and makes local development dependent on network access.

Structural Prerequisites

The technique requires a specific Lambda handler structure before mocking becomes practical:

  • Global scope: initialize AWS service connections once outside the handler, not inside it, to avoid repeated initialization per invocation.
  • Resource classes: wrap boto3 connections in classes that accept the connection as a parameter. This makes substitution during tests straightforward.
  • Separated business logic: move all non-orchestration logic into standalone functions called by the handler. The handler's only job is to instantiate resource classes and delegate.
  • Explicit dependency passing: pass resource class instances into downstream functions as arguments rather than accessing globals directly inside business logic.

This separation of concerns — handler orchestration / business logic / AWS integration — is what makes mocking possible without rewriting the function under test.

Mocking Strategy

Moto intercepts boto3 calls via decorators applied to test methods or classes. Under a Moto decorator, any boto3 call that would reach AWS is redirected to an in-memory simulation.

@moto.mock_dynamodb
@moto.mock_s3
def test_my_function(self):
    # arrange: create tables and objects in mock
    # act: call the function
    # assert: verify outcomes

setUp() and tearDown() lifecycle methods create and destroy the mocked resources around each test, keeping state isolated between runs.

Arrange-Act-Assert Pattern

Test construction follows three steps:

Step Action
Arrange Create mocked AWS resources; load test event from JSON file
Act Invoke the Lambda handler or business logic function directly
Assert Verify return values, side effects in mocked resources

Test events are stored as external JSON files rather than inline dictionaries, keeping test code readable as event payloads grow.

Network Isolation

pytest-socket disables real network connections during test runs. Any code path that attempts an actual AWS API call fails immediately, making it impossible for a test to accidentally reach production infrastructure.

Supporting Tools

Tool Role
Moto Mock AWS services in-process
pytest Test runner and fixture management
pytest-socket Enforce network isolation
AWS Lambda Powertools Structured logging, tracing, input validation for Lambda

Radar Assessment

Lambda Unit Testing with Moto sits in the Assess ring of the Techniques quadrant, at center position. The technique is well-established in the serverless community but carries a structural prerequisite: Lambda handlers must be refactored to separate orchestration, business logic, and AWS integration before mocking becomes practical. That upfront cost makes this different from a tool adoption — it requires a commitment to restructuring existing code. First exposure was via the AWS DevOps Blog on 2026-05-16. No personal implementation to date. Center position reflects that a trial is feasible once a suitable Lambda project arises, but is not immediately actionable without handler refactoring.

Clone this wiki locally