End to End Testing focuses on testing the entire flow of the application to ensure they work as designed. E2E testing differs from Unit testing, which focuses on testing the smallest units of code, mostly functions or methods. Testing an express route helps catch any errors that might occur while in the development stage, which can boost productivity.
Follow through with this tutorial to develop your first RESTful API E2E test.
End to End Testing, often called E2E testing or system testing, is a software testing technique which ensures that the application works as designed. It runs the application from start to finish, checking for any flaws in the development stage before moving to deployment. E2E testing ensures that the application meets business requirements and users’ expectations.
Unit testing is also a testing technique done in the development stage, but it involves the testing of individual components of an application.
These various testing methodologies have their benefits and drawbacks. Unit testing is better at catching errors because it isolates each component compared to E2E, which tests the application as a whole. E2E, on the other hand, ensures that the application is built as intended, meeting users’ expectations.
You can decide whether to pick any of the testing techniques or explore more options like Integration testing.
The importance of software testing cannot be overemphasized, as it offers vast benefits. The list below contains just a few:
The list can go on and on. This shows how testing is a very crucial part of developing software. With this knowledge, we can build an express application and test it to see if it works as proposed.
Make sure you have the following to effectively follow this article:
npm i -g yarn
. This will install yarn globally.Enough with the theory part. Let’s get our hands on some code. We will develop a payment API using Express and MongoDB as the database.
In this tutorial, we will create an API that will allow users:
To simply demonstrate how testing works, the money that will be used will be virtual, as we will not make use of any payment platform.
To get started, we need to install the needed dependencies. Create an empty folder called apitest
, you can name the folder as you please. Next, open this folder in your terminal and run the following:
Based on the above code, we created a package.json
file with default content using yarn init --yes
, then we installed the various dependencies and devDependencies.
Next, we will initialize the default config for typescript using the code below:
This will create a new tsconfig.json file with:
Modify the package.json file by replacing the script section with the one below.
Once we have installed the required dependencies, we will set up MongoDB Atlas next.
Navigate to Atlas’ webpage and register if you don't have an account or log in if you are an existing user.
On your dashboard, create a new database:
On the next screen, you will be asked to choose a plan. Select MO Free and click on the Create button. You can choose to select any other plan of your choice.
Enter the user username and password of your choice and click on Create User.
On the left nav bar, select Network Access and click on ADD IP ADDRESS
You can either choose to access the Atlas database from any device or you can specify the IP Address of your desired device. Once you’ve added an IP ADDRESS, click on the Confirm button.
After we’ve set up the database, the next step is to connect the application to MongoDB.
There are various methods to do this, but we will make use of Mongoose.
Select Database by the side nav bar on your Atlas dashboard. Click on the Connect button.
Click on Drivers.
Scroll to step 3 and copy the connection string
Next, open the apitest folder in Visual Studio Code, create a file called .env in the root folder and add the connection string as shown below:
Replace yourUsername
and yourPassword
with your specified username and password, respectively.
Following the addition of the connection string to the .env file,
Above, we created an express server that runs on the port received from the .env file or on port 5000
.
Once we’re done setting up the server, the next step is to connect to MongoDB.
To do this, create a folder in the src folder called config and a file in the config called db.ts.
Add the code below to the db.ts file once you have created it.
Next, import the connectDB
function from the db.ts file into the server.ts file.
After connecting to the database, we will create the account schema. In this schema, we will create a blueprint for the Mongo database containing:
Create a model in the src folder called model and create a file in it, Account.ts.
Add the following to the Account.ts file:
In this section, we will set up different routes for the express application.
These routes include:
/api/signup
/api/login
/api/deposit
/api/transfer
api/find/:username
We will create a boiler template that will handle the routes' functions.
Create a folder called Controller, create a file called index.ts in it, and add the code below to the file.
Next, create a folder, routes, and ****add the following files and their respective codes to it.
Lastly, import these various routes into the server.ts file and use them.
In this section, we will add the functionalities for the various routes.
Open the index.ts file in /src/Controller and let’s handle the signup
function.
Above, we used the username and password that will be passed to the request body to create a new account. For the simplicity of this project, we did not hash out the password. This is not acceptable. All passwords must be hashed first using services like bcrypt or crypto before storing them in the database. Hashing your password helps to protect its content even when the database is accessed by unauthorized users.
Next, we will handle the login
function.
We got the username and password from req.body
and checked if the password in the database for that user matches the one provided.
After handling the signup and login functionality, the deposit
function comes next.
Based on the code above, we performed the login logic and then added the specified amount to the user’s account.
Now, we will handle the transfer
function.
In the code above, we also performed the login logic and
Lastly, we will handle the find
function.
In the previous functions, we got the username from the request body but in the find
function, we got the username from the request parameter. We saved the username and then searched the database for the corresponding user to retrieve their balance.
Feel free to manually test out the route using Postman or Thunder Client in Visual Studio Code.
Once all the setups are done, it’s time to dive into the main cause of this article, which is Testing.
To start testing the express routes, you need to get a separate database for your testing. It is not ethical to have the same database for your test and primary application.
You can follow the section where we set up the database to create a database for testing.
After you’ve created the database, add the test connection string to the .env file.
Create a function in the db.ts file that will connect to the test database.
Open your terminal and run npm install @faker-js/faker --save-dev
to install the faker package. Faker helps to generate realistic data that is employed in populating the database and in testing.
Next, create a file named jest.config.js in the root directory and add the code below to it. Jest makes use of this file to config the E2E testing for the application.
Above, we indicated the duration (10,000 milliseconds) that Jest will pause for a test to run before proceeding to subsequent tests.
Create a folder in the root directory called .jest, create a file named setEnvVars.js in it, and add the following:
Following the setup of Jest, the next step involves creating a file designated for E2E testing in this application. You can choose to name this file as you please but in this tutorial, it’s called app.test.ts.
Add the following to it:
We imported the test database into the test file and then invoked the beforeAll
method. This method initiates a connection with the test database before proceeding with the execution of other tests.
After the initialization of the database, we will create a test for the signup
route. In this test, we will check for the route with both valid and invalid values.
This will help to ensure that the application runs as designed and detects errors if any.
Based on the above code, we generated fake usernames and a password using the Faker library.
Once these fake credentials were created, we created two different tests. In the first test, we passed valid data to the request body while in the second, we passed empty data.
With the creation of the register
route now in place, we will test the login
route.
Jest executes these tests in consecutive order, hence the organization of your tests holds great significance.
After testing the register
route, we used the same username and password to test the login functionality.
Next, we will test the deposit
route.
In the successful test, we deposited a specified amount of money to the same username while in the invalid test, we passed 0
as the amount to be deposited.
Now that we have money in the user’s account, we will test out transferring this money to another user.
5000
was deposited into the user’s account in thedeposit
route.
In the test marked as successful, we transferred 1000 to the recipient, while in the case of the invalid route, we attempted to transfer a sum exceeding the user's balance.
Lastly, we will test thefind
route.
Now that all the tests for the express route have been written, we can now run the test command.
Launch your terminal and execute npm run test
to initiate the testing process.
Verify that all the written tests have successfully passed. If needed, you can refer to the source code of the tutorial available here.
In this tutorial, we comprehensively covered the process of setting up and conducting tests for an express route. With this basic knowledge, you can conduct tests for complex applications.