Imagine your web application is using MongoDB to store its data. How would you take advantage of it during Cypress tests? This blog post shows how to clear the data from a local Mongo database before each test by connecting to the DB directly from the Cypress plugin file.
The setup
My "application" is very simply - it is a single API endpoint that collects pizza information. You can post new pizza names plus ingredients and get the full list.
1 | const { connect } = require('./db') |
The Mongo connection is made in the file db.js
shown below:
1 | const { MongoClient } = require('mongodb') |
🎁 You can find the source code at bahmutov/cypress-example-mongodb.
Notice that we connect to the Mongo instance using the single connection string from the MONGO_URI
environment variable.
Run Mongo locally
The simplest way to run Mongo instance locally is by using Docker container, read this post.
1 | docker pull mongo |
The above command starts a new container called mongo-on-docker
using the pulled image mongo
. The container will expose the port 27017 (Mongo's default port for connection). We also pass the admin user name and password we want to use.
The user name and the password then can be used to create the connection string environment variable:
1 | MONGO_URI=mongodb://mongoadmin:secret@localhost:27017/?authSource=admin |
Tip: to stop and remove the container later use the following commands:
1 | docker stop mongo-on-docker |
Start the server
After starting the Mongo DB instance, we can start the server. We can pass the MONGO_URI
inline
1 | MONGO_URI=mongodb://mongoadmin:secret@localhost:27017/?authSource=admin \ |
A better idea is to use as-a to keep the secret environment variable outside the repository and easily inject them when running the commands. Thus I place the MONGO_URI
into ~/.as-a/.as-a.ini
file
1 | [mongo-example] |
and start the server like this after installing as-a
globally
1 | npm i -g as-a |
Super, we can hit the server endpoint /pizza
from the command line to check:
1 | curl http://localhost:8080/pizza |
The first API test
Let's write Cypress API test using cy.request command.
We will always hit the local URL, so let's place it into the baseUrl
setting in the configuration file cypress.json
:
1 | { |
1 | /// <reference types="cypress" /> |
Let's write a test that adds a pizza and verifies it is returned.
1 | /// <reference types="cypress" /> |
The tests pass. One advantage of using Cypress to work with API tests is that you can inspect every request to see what was returned. For example, by clicking on the cy.request
in the second test we can see the full list of returned objects.
Tip: did you notice that during the API tests the application's iframe stays empty? You can pipe the request information there, see the cy-api project.
Clear the collection
If we re-run the tests again, our tests fail.
Of course, we have never cleared the collection of objects before the tests, so the database keeps them around. How should we clear the collection, if the API does not expose the clear method?
By connecting to the Mongo database directly from the Cypress test runner and clearing it using a cy.task command. Let's add the following code to the plugin file:
1 | /// <reference types="cypress" /> |
Tip: Cypress v6+ comes with Node v12+ built-in, thus we can use all the modern ES6 syntax like async / await
sugar to write asynchronous code.
From the spec file, we should all the clearPizzas
task before the tests start.
1 | describe('Pizzas', () => { |
Because Cypress needs to connect to the Mongo instance (just like the server.js), we start it by passing the MONGO_URI
environment variable. The plugin file runs in Node, requires the db.js
file, which uses that environment variable to connect.
1 | as-a mongo-example npx cypress open |
We can now write more tests, if we want to
1 | /// <reference types="cypress" /> |
And they all pass
Testing on CI
I will run the same tests on CircleCI using the Cypress Orb. To run MongoDB we can use a service container that spins the second Docker container linked to the first one (where our server and tests execute) automatically. See the Cypress recipes for more examples.
1 | version: 2.1 |
In the CircleCI project's page set the environment variables MONGO_USERNAME
and MONGO_PASSWORD
to use during testing. The Circle YML file forms the MONGO_URI
environment variable to use in the server and Cypress to connect from those user name and password values.
Push a new commit to the repository to trigger the build. The build should pass.
You can drill down to see the individual test steps performed by the orb. For example, you can see the log output from the Mongo container running during the entire test job.
And you can see the output from the server and from Cypress tests. Clearing the collection, adding new pizzas, all that delicious jazz.
Happy testing!