Testing - ALawliet/backend GitHub Wiki
people seem to recommend
- unit test what you can, business logic, that things get called, you can mock AWS events and services
- to hit lambdas locally, use SAM local or Serverless Offline. SAM local seems more popular, it can also generate event templates
- run AWS locally
- can use LocalStack to test infra as code and cli tools, or as a more realistic mock with mini AWS services running locally
- if just SQS/SNS, can use goaws
- if just ddb, can use ddb local
- then use infra as code to deploy to an AWS test environment and integration test there with real resources
https://madhead.github.io/aws-junit5/asciidoc/#_bonus_ci_with_github
https://aws.amazon.com/blogs/opensource/testing-aws-lambda-functions-written-in-java/
https://docs.aws.amazon.com/lambda/latest/dg/testing-guide.html
https://openupthecloud.com/how-to-test-aws-lambda/
https://aws.amazon.com/blogs/devops/unit-testing-aws-lambda-with-python-and-mock-aws-services/
- framework: JUnit5
- mocks
- Java -> Mockito
- Kotlin -> Mockk
- assertions: AssertJ, Hamcrest, Kotest
- AWS: aws-lambda-java-tests, aws-junit5
- test coverage report: Jacoco
- test against real database and mock AWS: Testcontainers, Localstack
what to test:
- mock trigger
- that lambda handler is called with an input
- that business logic is called
- validate business logic output
- input/output should use data class and @ParameterizedTest
things to mock:
- data access, databases
- external services we didn't write
- stuff on the cloud
- AWS services/events like SQS, S3
- event json templates
things that can be tested locally:
- isolated business logic
- that things get called
things that may pass locally but fail on the cloud:
- cloud config
- service limitations
https://www.youtube.com/watch?v=fLVUlJ-i_Qs&ab_channel=thenewboston
- Fast
- Isolated
- Repeatable
- Self-validating
- Timely
https://www.youtube.com/watch?v=RX_g65J14H0&ab_channel=JetBrains, https://phauer.com/2018/best-practices-unit-testing-kotlin/
- JUnit5
@TestInstance(PER_CLASS)
- Naming (Backticks), Grouping (Nested)
- Libraries
- Mockk
- AssertJ
- Mock Handling
- Don't recreate; reset!
- Data Classes FTW
- Equals Assertions
- Creation Helper
- @ParameterizedTest
https://www.youtube.com/watch?v=s6idLikuovc&ab_channel=BrandanJones
- it's too complicated -> it's your code, not the test!
- it interacts with external data -> used Mocked objects, create an object and tell it how to behave when used in the test
- it calls something outside (a REST endpoint, external service, or something we don't control) -> use verify
- verify something was called, with a certain set of parameters, x amount of times
https://www.youtube.com/watch?v=Mu0mWa6th4c&ab_channel=JamesEastham
- unit test locally, test everything else in the cloud with actual cloud resources for more complicated stuff
- unit test should have no external dependencies, mock those
- data access
- @ParameterizedTest, @Event for APIGatewayProxyRequest
- can use mocks to simulate throwing exceptions
- can use debugger on code while test runs to step through business logic locally
- SAM local
sam buildruns the unit tests
ArgumentCaptor<Product> productArgumentCaptor = ArgumentCaptor.forClass(Product.class);
Mockito.verify(testDataAccessClient).StoreProduct(productArgumentCaptor.capture());https://www.youtube.com/watch?v=RienImDKxlo&ab_channel=DiegoPacheco
- aws-lambda-java-tests
- allows simulating different triggers using event.json files: SQS, S3, Cloudwatch
- make an event where you have the message in detail, another one where you're missing the message, etc.
ScheduledEvent event = eventLoader.loadScheduledEvent("event.json")
@ParameterizedTest
@Event(value = "event.json", type = ScheduledEvent.class)
public void testLoadEventBridgeEvent(ScheduledEvent event) {}- requires Docker
- uses CloudFormation, so it looks similar to their templates
- creates an S3 bucket to store artifacts
https://www.youtube.com/watch?v=AUQRyl1SNcU&ab_channel=BeABetterDev
- just AWS::Serverless construct
- template.yaml with different setups for regular lambda function, from APIGW, SNS, etc.
sam local invoke -e ./lambda/lambda_event.json LambdaDemoFunctionhttps://www.youtube.com/watch?v=ku80wC3QqwQ&ab_channel=BeABetterDev
- with CDK, which spits out CF, so it's a matter of if you want to write a SAM yaml template or CDK in your language
sam local invoke -t ./cdk.out/CdkLambdaLocalStack.template.json
sam local generate-event sns notification
sam local invoke -t ./cdk.out/CdkLambdaLocalStack.template.json -e ./events/sns_event.jsonhttps://www.youtube.com/watch?v=fEZE3rm8Ma8&ab_channel=TravisMedia
https://www.youtube.com/watch?v=HsQ9OwKA79s&t=908s&pp=ygUHbW9ja2l0bw%3D%3D
https://www.youtube.com/watch?v=MztH6vkeFVk&t=167s&ab_channel=AneeshMistry
https://www.youtube.com/watch?v=aNCPy803rkI&t=576s&ab_channel=CodingSimplified
https://aws.amazon.com/blogs/opensource/testing-aws-lambda-functions-written-in-java/
https://www.youtube.com/watch?v=ATo19E6oegE&ab_channel=DevOpsJourney
https://www.youtube.com/watch?v=SYCeM-Q6nRs&t=2s&pp=ygUObG9jYWxzdGFjayBjZGs%3D
is more of a standard for using containers in JUnit, so should probably use this instead of localstack-utils
https://www.youtube.com/watch?v=3_sqr0G9zb0&t=260s&pp=ygUObG9jYWxzdGFjayBjZGs%3D
- can use SAM local/CDK to deploy to LocalStack to test IaC locally instead of cloud
https://www.youtube.com/watch?v=eszNbLXoaGQ&pp=ygUObG9jYWxzdGFjayBjZGs%3D
https://aws.amazon.com/blogs/compute/better-together-aws-sam-and-aws-cdk/
CF/SAM template -> AWS SAM CLI
CDK -> AWS SAM CLI
-> LocalStack
https://www.playingaws.com/posts/how-to-create-serverless-applications-with-cdk-and-sam/
- CDK to build lambdas and synth to CF (instead of SAM template)
- SAM to test invoke against them
- spin up local DDB in Docker
https://fourco.nl/blogs/speeding-up-lambda-development/
- SAM Accelerate avoids deploying the whole application through CF for small changes of code