Run Node.js tests in a container
Prerequisites
Complete all the previous sections of this guide, starting with Containerize a Node.js application.
Overview
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 take a look at running your unit tests in Docker when developing and when building.
Run tests when developing locally
The sample application already has the Jest package for running tests and has tests inside the spec
directory. When developing locally, you can use Compose to run your tests.
Run the following command to run the test script from the package.json
file inside a container.
$ docker compose run server npm run test
To learn more about the command, see docker compose run.
You should see output like the following.
> docker-nodejs@1.0.0 test
> jest
PASS spec/routes/deleteItem.spec.js
PASS spec/routes/getItems.spec.js
PASS spec/routes/addItem.spec.js
PASS spec/routes/updateItem.spec.js
PASS spec/persistence/sqlite.spec.js
● Console
console.log
Using sqlite database at /tmp/todo.db
at Database.log (src/persistence/sqlite.js:18:25)
console.log
Using sqlite database at /tmp/todo.db
at Database.log (src/persistence/sqlite.js:18:25)
console.log
Using sqlite database at /tmp/todo.db
at Database.log (src/persistence/sqlite.js:18:25)
console.log
Using sqlite database at /tmp/todo.db
at Database.log (src/persistence/sqlite.js:18:25)
console.log
Using sqlite database at /tmp/todo.db
at Database.log (src/persistence/sqlite.js:18:25)
Test Suites: 5 passed, 5 total
Tests: 9 passed, 9 total
Snapshots: 0 total
Time: 2.008 s
Ran all test suites.
Run tests when building
To run your tests when building, you need to update your Dockerfile to add a new test stage.
The following is the updated Dockerfile.
# syntax=docker/dockerfile:1
ARG NODE_VERSION=18.0.0
FROM node:${NODE_VERSION}-alpine as base
WORKDIR /usr/src/app
EXPOSE 3000
FROM base as dev
RUN --mount=type=bind,source=package.json,target=package.json \
--mount=type=bind,source=package-lock.json,target=package-lock.json \
--mount=type=cache,target=/root/.npm \
npm ci --include=dev
USER node
COPY . .
CMD npm run dev
FROM base as prod
RUN --mount=type=bind,source=package.json,target=package.json \
--mount=type=bind,source=package-lock.json,target=package-lock.json \
--mount=type=cache,target=/root/.npm \
npm ci --omit=dev
USER node
COPY . .
CMD node src/index.js
FROM base as test
ENV NODE_ENV test
RUN --mount=type=bind,source=package.json,target=package.json \
--mount=type=bind,source=package-lock.json,target=package-lock.json \
--mount=type=cache,target=/root/.npm \
npm ci --include=dev
USER node
COPY . .
RUN npm run test
Instead of using CMD
in the test stage, use RUN
to run the tests. The reason is that the CMD
instruction runs when the container runs, and the RUN
instruction runs when the image is being built and the build will fail if the tests fail.
Run the following command to build a new image using the test stage as the target and view the test results. Include --progress=plain
to view the build output, --no-cache
to ensure the tests always run, and --target test
to target the test stage.
$ docker build -t node-docker-image-test --progress=plain --no-cache --target test .
You should see output containing the following.
...
#11 [test 3/3] RUN npm run test
#11 1.058
#11 1.058 > docker-nodejs@1.0.0 test
#11 1.058 > jest
#11 1.058
#11 3.765 PASS spec/routes/getItems.spec.js
#11 3.767 PASS spec/routes/deleteItem.spec.js
#11 3.783 PASS spec/routes/updateItem.spec.js
#11 3.806 PASS spec/routes/addItem.spec.js
#11 4.179 PASS spec/persistence/sqlite.spec.js
#11 4.207
#11 4.208 Test Suites: 5 passed, 5 total
#11 4.208 Tests: 9 passed, 9 total
#11 4.208 Snapshots: 0 total
#11 4.208 Time: 2.168 s
#11 4.208 Ran all test suites.
#11 4.265 npm notice
#11 4.265 npm notice New major version of npm available! 8.6.0 -> 9.8.1
#11 4.265 npm notice Changelog: <https://github.com/npm/cli/releases/tag/v9.8.1>
#11 4.265 npm notice Run `npm install -g npm@9.8.1` to update!
#11 4.266 npm notice
#11 DONE 4.3s
...
Summary
In this section, you learned how to run tests when developing locally using Compose and how to run tests when building your image.
Related information:
Next steps
Next, you’ll learn how to set up a CI/CD pipeline using GitHub Actions.