Joyce
Joyce

Reputation: 1451

how would one run aws lambda locally (java) for testing

How would one run aws lambda locally (java) for testing.

I was able to find some information for node, but not for java.

Upvotes: 27

Views: 29804

Answers (8)

Sanjay Bharwani
Sanjay Bharwani

Reputation: 4739

We use localstack to mock AWS.

Here is the docker-compose.yaml

version: "3.3"
    services:
      localstack:
        container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
        image: localstack/localstack:1.2.0
        ports:
          - "4566:4566"            # LocalStack Gateway
        environment:
          - DEBUG=${DEBUG-}
          - PERSISTENCE=${PERSISTENCE-}
          - LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR-}
          - DOCKER_HOST=unix:///var/run/docker.sock

Now we have functional tests which creates a Lambda function on this localstack (mocked AWS)

 import software.amazon.awssdk.services.lambda.LambdaClient;
private LambdaClient lambdaClient;
private final AwsBasicCredentials awsCreds = AwsBasicCredentials.create("id", "key");

Below code creates a lambdaClient to interact with localstack

lambdaClient = LambdaClient.builder()
      .endpointOverride(URI.create("http://localhost:4566"))
      .region(Region.EU_WEST_1)
      .credentialsProvider(StaticCredentialsProvider.create(awsCreds))
      .build();

Now using this lambdaClient, we can deploy the lambda function on localstack. We need a zip file of the code.

   createLambdaFunction(lambdaClient, "first-serverless-lambda", zipFilePath, "", "com.example.serverless.SampleLambda", new HashMap<>(Map.of("env-var-1","env-var1-val"));

And here is the implementation of createLambdaFunction

public static void createLambdaFunction(LambdaClient lambdaClient,
                                          String functionName,
                                          String filePath,
                                          String role,
                                          String handler,
 Map<String, String> config                                       ) {

    try {
      var waiter = lambdaClient.waiter();
      var is = new FileInputStream(filePath);
      var fileToUpload = SdkBytes.fromInputStream(is);

      lambdaClient.createFunction(builder -> builder.functionName(functionName)
        .description("Created by the Lambda Java API")
        .code(codeBuilder -> codeBuilder.zipFile(fileToUpload))
        .handler(handler)
        .runtime(Runtime.JAVA11)
        .environment(environmentBuilder -> environmentBuilder.variables(config))
        .role(role));
      
      waiter.waitUntilFunctionExists(builder -> builder.functionName(functionName)).matched();

    } catch (LambdaException | FileNotFoundException e) {
      System.out.println(e.getMessage());
    }
  }

References: https://github.com/localstack/localstack

Upvotes: 0

Songtao Lou
Songtao Lou

Reputation: 51

There is a new upgrade for Lambda java test.

@Test 
public void testLoadEventBridgeEvent() throws IOException {
    // Given
    ObjectMapper objectMapper = new ObjectMapper();
    InputStream eventStream = this.getClass().getResourceAsStream("event.json");
    ScheduledEvent event = objectMapper.readValue(eventStream, ScheduledEvent.class);
    EventHandler<ScheduledEvent, String> handler = new EventHandler<>();
    
    // When
    String response = handler.handleRequest(event, contextMock);
    
    // Then
    assertThat(response).isEqualTo("something");
}

Please read this article https://aws.amazon.com/cn/blogs/opensource/testing-aws-lambda-functions-written-in-java/?nc1=h_ls

Upvotes: 0

Hims
Hims

Reputation: 1

If you are using IntelliJ there is aws-toolkit - https://plugins.jetbrains.com/plugin/11349-aws-toolkit/

It works very well, you can set environment variables etc. It will require you to have docker running on your local machine. Not very memory friendly though.

If you are using serverless, you can do sls offline.

Upvotes: 0

Joyce
Joyce

Reputation: 1451

I have been using these docker images https://github.com/lambci/docker-lambda

Upvotes: 0

Mrk Fldig
Mrk Fldig

Reputation: 4486

There are a number of projects going on to run the entire AWS stack locally.

Java I believe the main option is Localstack

If you're on Javascript you can go Serverless

Upvotes: 2

asokan
asokan

Reputation: 353

SAM Local - http://docs.aws.amazon.com/lambda/latest/dg/test-sam-local.html and docker-lambda - https://github.com/lambci/docker-lambda have worked well for APIs that need only javaee and project sources. I am still trying to figure out how to set to set the classpath to include the gradle dependencies.

Upvotes: 4

Marcelo Glasberg
Marcelo Glasberg

Reputation: 30879

You can use AWS Toolkit for Eclipse if you want to perform local testing for Amazon Lambda functions, and build serverless applications in Amazon.

But since Aug 11, 2017, Amazon provides the AWS SAM Local, a CLI tool that allows us to locally test and debug our AWS Lambda functions. SAM Local supports Lambda functions written in Node.js, Java, and Python.

Please vote for implementing Intellij IDEA support for Amazon Lambda here:

Upvotes: 4

Mircea
Mircea

Reputation: 10566

AFAIK there is no magic to actually triggering the lambda function locally. Take a look at: http://docs.aws.amazon.com/lambda/latest/dg/java-programming-model-req-resp.html
and
http://docs.aws.amazon.com/lambda/latest/dg/java-gs.html

Depending what your lambda code does you need to build the input and (possibly the context) and pass them into the function writing your own small test wrapper.

Unless you are doing this for unit testing it does not make sense to go through the trouble though. If you are doing this for testing you will probably need to mock out other external AWS services that your lambda might use.

Upvotes: 8

Related Questions