Local Testing of AWS Serverless Lambda Functions

Jens Knipper

  • Software Engineer
  • OpenValue Düsseldorf GmbH
  • curious about new technologies
  • likes well tested software!

Agenda

  • Testing of Microservices
  • Introduction to Lambda Functions
  • Testing of Lambdas
  • Example Use-Case
  • Demo

Testing of Microservices

Database Adapter

Service Layer

Domain

External Service

External Database

HTTP Adapter

REST Adapter

in Hexagonal Architecture*

* martinfowler.com/articles/microservice-testing

Testing of Microservices

Unit-Tests

Database Adapter

Service Layer

Domain

External Service

External Database

HTTP Adapter

REST Adapter

Testing of Microservices

Integration-Tests

Database Adapter

Service Layer

Domain

External Service

External Database

HTTP Adapter

REST Adapter

Testing of Microservices

Component-Tests

Database Adapter

Service Layer

Domain

External Service

External Database

HTTP Adapter

REST Adapter

Testing of Microservices

Database Adapter

Service Layer

Domain

External Service

External Database

HTTP Adapter

REST Adapter

Summary

Testing of Microservices

Unit

Integration

Component

Manual

Summary

e2e

Unit

Introduction to Lambdas

  • simple function - very small!
    • e.g. no webserver needed
  • triggered by event
    • custom
    • AWS specific
      • e.g. fileupload to S3
  • scales automatically
  • runs your function only when needed
    • pay what you consume
    • no load - no lambda running

Introduction to Lambdas

  • size constrained by framework
    • only one event allowed
    • no tendency to grow
  • can be used in a Microservices architecture
    • API Gateway required

Testing of Lambdas

  • Lambdas can be Microservices!
    • testing should be the same!
  • same tools
    • Dependency Injection
    • Testcontainers
    • Wiremock
    • ...
  • new tools
    • LocalStack

Example Use-Case

public class EventHandler 
	implements RequestHandler<Input, Output> {
  ...

  public EventHandler() {
    final StorageService storageService = new StorageService(...);
    final ImageService imageService = new ImageService(...);
    
    this.eventHandlingService = 
    	new EventHandlingService(storageService, imageService);
  }

  @Override
  public Output 
  	handleRequest(final Input input, final Context context) {
    return eventHandlingService.handleEvent(input);
  }

Example Use-Case

EventHandler

public class Input {
  private String bucket;
  private String key;
  
  ...
 }

Example Use-Case

Input & Output

public class Output {
  private String bucket;
  private String key;
  
  ...
 }

Example Use-Case

public class EventHandlingService {
  private final StorageService storageService;
  private final ImageService imageService;

  public EventHandlingService(...) {
    ...
  }

  public Output handleEvent(final Input input) {
    final InputStream inputStream = storageService.getObject(...);
    ...
    final BufferedImage newImage = imageService.resize(...);
    ...
    storageService.uploadFile(...);
    return new Output(...);
  }
}

EventHandlingService

Demo

Summary

  • manual Dependency Injection
    • independent testing
  • Hexagonal Architecture
    • testing external dependencies
  • component tests
    • ensure Lambda is executable
  • reliable test suite for automatic testing

Other Clouds?

  • Microsoft Azure
    • Azurite
  • Google Cloud Platform
    • Google App Engine local development server

Resources

Thank you!

Please ask questions.

jens@openvalue.de

@OpenValue

openvalue.eu