Example case: Bartender Server. 🍻
Responsible for:
- Providing a menu of drinks on a REST API
- Collecting incoming orders from a message queue
- Persisting orders in a database for bookkeeping
- Collecting payment for orders using a payment-provider
- Sending events to a topic when an order is ready
More information is found here:
- Slideshow ( Google docs)
You can see that the 5 responsibilities also require 4 external systems (queue, payments, database, topic), and it provides a service for external users (REST-API).
We need an end-to-end tests to have some confidence that our backend works with these external systems. Mocking them in tests will not be good enough.
(For real confidence, you can go even further and create system tests, where you inject data into a real, deployed AWS account as part of your CD-pipeline. This is out of scope for this course.)
The Main
-file starts the application.
It loads a Config
into an App
.
The app starts serving the REST-API, and starts an SqsPoller
to read from its SQS queue.
The API provides the output of GetDrinkMenuRoute
.
The SQS poller loops forever, fetching new messages and sending them to a queue processor named OrderQueueProcessor
.
The OrderQueueProcessor
coordinates several services and persists to the database.
Then, an event is sent out using OrderReadyNotifyer
.
The code largely works (I think? No tests to verify...).
The tests, however, are missing.
TODO-list:
- Test-setup
- Database: Testcontainers Postgres
- AWS SQS and SNS: Testcontainers Localstack
- Payments provider: Wiremock
- Tweak config with correct values
- OrderRepositoryTes needs some assertions.
- AssertJ
- verifyJsonSnapshot
- ApiEndToEndTest needs some assertions.
- RestAssured
- verifyJsonSnapshot
- OrderProcessingEndToEndTest needs some input and assertions.
- Inspect the SNS published messages: Awaitility + http client + localstack API
- Storage: database SELECT
- Payment provider: Wiremock verify
- Inspect SQS available messages count == 0
See the docs in docs/ for references on testing-llibraries used.
You need to install:
- Docker
- Maven (or run maven through IntelliJ)
- JDK 17
brew tap homebrew/cask-versions
and thenbrew install --cask temurin17
git clone git@github.com:krissrex/capra-e2e-testing-kotlin-backend-course.git
IntelliJ → File
→ New
→ Project from existing sources...
→ capra-e2e-testing-kotlin-backend-course
.
Choose "Import project from external model" and select Maven
.
Run ./init-local-env.sh
once to create overrides.properties
to tweak settings.
Start Main.kt.
You should use ./scripts/build.sh
, then ./scripts/run.sh
or ./scripts/run-docker.sh
.
Or run no.liflig.bartenderservice.Main.main()
from IntelliJ.
The app needs a Postgres database, an SQS message queue, and an SNS pub/sub topic.
- Build the jar:
mvn package
- Copy the jar from
target/app.jar
to/docker/app.jar
.
- You can use
./scripts/build.sh
.
- Run the app
- Start
docker-compose
:docker-compose -f docker-compose.yml up -d
- Or
./scripts/run-docker.sh
You can test the API with src/test/http/menu.http
AWS_ACCESS_KEY_ID=x AWS_SECRET_ACCESS_KEY=x aws --region=us-east-1 --endpoint-url=http://localhost:4566 sqs send-message --queue-url=http://localstack:4566/000000000000/orders-queue --message-body '{"orderId":"1","customer":{"id":"1","age":"TWENTY"},"paymentInfo":{"cardNumber":"123-1234-123-456"},"orderLines":[{"id":"1","name":"Hansa","price":"98","size":"0.6","ageLimit":"EIGHTEEN"},{"id":"4","name":"Hakkespett","price":"120","size":"0.4","ageLimit":"TWENTY"}]}'
or
awslocal sqs send-message --queue-url=http://localstack:4566/000000000000/orders-queue --message-body '{"orderId":"1","customer":{"id":"1","age":"TWENTY"},"paymentInfo":{"cardNumber":"123-1234-123-456"},"orderLines":[{"id":"1","name":"Hansa","price":"98","size":"0.6","ageLimit":"EIGHTEEN"},{"id":"4","name":"Hakkespett","price":"120","size":"0.4","ageLimit":"TWENTY"}]}'
mvn verify
Add -DskipTests
to mvn
to disable all tests.
Add -DskipITs
to only disable integration tests.
Only lint: mvn spotless:check
Fix: mvn spotless:apply
Copyright 2022 Liflig By Capra AS
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.