6.1 KiB
title | keywords | description |
---|---|---|
Run your Java tests | Java, build, test | How to build and run your Java tests |
Prerequisites
Work through the steps to build an image and run it as a containerized application in Use your container for development.
Introduction
Testing is an essential part of modern software development. Testing can mean a lot of things to different development teams. There are unit tests, integration tests and end-to-end testing. In this guide you'll take a look at running your unit tests in Docker.
Refactor Dockerfile to run tests
The Spring Pet Clinic source code has already tests defined in the test directory src/test/java/org/springframework/samples/petclinic
. You can use the following Docker command to start the container and run tests:
$ docker run -it --rm --name springboot-test java-docker ./mvnw test
...
[INFO] Results:
[INFO]
[WARNING] Tests run: 40, Failures: 0, Errors: 0, Skipped: 1
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:49 min
Multi-stage Dockerfile for testing
Now, you'll learn how to pull the testing commands into your Dockerfile. The following is your updated multi-stage Dockerfile that you'll use to build your test image. Replace the contents of your Dockerfile with the following.
# syntax=docker/dockerfile:1
FROM eclipse-temurin:17-jdk-jammy as base
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:resolve
COPY src ./src
FROM base as test
CMD ["./mvnw", "test"]
FROM base as development
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000'"]
FROM base as build
RUN ./mvnw package
FROM eclipse-temurin:17-jre-jammy as production
EXPOSE 8080
COPY --from=build /app/target/spring-petclinic-*.jar /spring-petclinic.jar
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/spring-petclinic.jar"]
You added a new build stage labeled test
. You'll use this stage for running your tests.
Now, rebuild your image and run your tests. You'll run the docker build
command like you did previously, but this time you'll add the --target test
flag so that you specifically run the test build stage.
$ docker build -t java-docker --target test .
[+] Building 0.7s (6/6) FINISHED
...
=> => writing image sha256:967ac80cb7799a5d12a4bdfc67c37b5a6533c6e418c903907d3e86b7d4ebf89a
=> => naming to docker.io/library/java-docker
Now that your test image is built, you can run it as a container and see if your tests pass.
$ docker run -it --rm --name springboot-test java-docker
[INFO] Scanning for projects...
[INFO]
[INFO] ------------< org.springframework.samples:spring-petclinic >------------
[INFO] Building petclinic 2.4.2
...
[INFO] Results:
[INFO]
[WARNING] Tests run: 40, Failures: 0, Errors: 0, Skipped: 1
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:22 min
The build output is truncated, but you can see that the Maven test runner was successful and all your tests passed.
This is great. However, you'll have to run two Docker commands to build and run your tests. You can improve this slightly by using a RUN
statement instead of the CMD
statement in the test stage. The CMD
statement isn't executed during the building of the image, but is executed when you run the image in a container. When using the RUN
statement, your tests run when building the image, and stop the build when they fail.
Update your Dockerfile with the following.
# syntax=docker/dockerfile:1
FROM eclipse-temurin:17-jdk-jammy as base
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:resolve
COPY src ./src
FROM base as test
RUN ["./mvnw", "test"]
FROM base as development
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000'"]
FROM base as build
RUN ./mvnw package
FROM eclipse-temurin:17-jre-jammy as production
EXPOSE 8080
COPY --from=build /app/target/spring-petclinic-*.jar /spring-petclinic.jar
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/spring-petclinic.jar"]
Now, to run your tests, you just need to run the docker build
command.
$ docker build -t java-docker --target test .
[+] Building 27.6s (11/12)
=> CACHED [base 3/6] COPY .mvn/ .mvn
=> CACHED [base 4/6] COPY mvnw pom.xml ./
=> CACHED [base 5/6] RUN ./mvnw dependency:resolve
=> CACHED [base 6/6] COPY src ./src
=> [test 1/1] RUN ["./mvnw", "test"]
=> exporting to image
=> => exporting layers
=> => writing image sha256:10cb585a7f289a04539e95d583ae97bcf8725959a6bd32c2f5632d0e7c1d16a0
=> => naming to docker.io/library/java-docker
The build output is truncated for simplicity, but you can see that your tests ran successfully and passed. Look at one of the tests and observe the output when your tests fail.
Open the src/test/java/org/springframework/samples/petclinic/model/ValidatorTests.java
file and change the following assertion.
- assertThat(violation.getMessage()).isEqualTo("must not be empty");
+ assertThat(violation.getMessage()).isEqualTo("must be empty");
Now, run the docker build
command and observe that the build fails and the failing testing information is printed to the console.
$ docker build -t java-docker --target test .
=> [base 6/6] COPY src ./src
=> ERROR [test 1/1] RUN ["./mvnw", "test"]
...
------
executor failed running [./mvnw test]: exit code: 1
Next steps
In this module, you took a look at running tests as part of your Docker image build process.
In the next module, you’ll take a look at how to set up a CI/CD pipeline using GitHub Actions.
{{< button text="Configure CI/CD" url="configure-ci-cd.md" >}}