Skip to content

Instantly share code, notes, and snippets.

@tatsuyasusukida
Last active September 8, 2022 01:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tatsuyasusukida/c21445d4a36b07013d79b2baa54e6d61 to your computer and use it in GitHub Desktop.
Save tatsuyasusukida/c21445d4a36b07013d79b2baa54e6d61 to your computer and use it in GitHub Desktop.
✌️ How to automate API testing of web apps with fetch in Node.js [video version available]

✌️ How to automate API testing of web apps with fetch in Node.js [video version available]

Video thumbnail: How to automate API testing of web apps with fetch in Node.js

About this article

This article describes how to automate API testing by using fetch in Node.js. We install node-fetch npm package to enable fetch in Node.js.

Workflow

The workflow is as follows:

  1. Preparing to write source code
  2. Writing source code
  3. Preparing to write test code
  4. Writing test code
  5. Operation check

Preparing to write source code

Execute the following command in the terminal to prepare for coding.

mkdir nodejs-test-api
cd nodejs-test-api
npm init -y
npm install --save express
npm install --save-dev node-fetch@2
touch api.js

If you want to import node-fetch using require (require('node-fetch')), it needs to be version 2, so add @2 to the end and install it.

Writing source code

api.js

Open api.js in an editor and enter the following content

Click to go to api.js

Preparing to write test code

Execute the following command in the terminal to prepare for coding.

touch api.test.js

Writing test code

api.test.js

Open api.test.js in an editor and enter the following content.

Click to go to api.test.js

The points are as follows:

  1. Import node-fetch as fetch.
  2. Call the fetch function to access the API.
  3. Use assert.strictEqual to check that the actual value, such as the status code, matches the expected value.
  4. It is convenient to use assert.deepStrictEqual to check the whole object match.

Operation check

Execute the following command in the terminal to start the API.

node api.js

Open a new terminal and run the following command to run the API test.

node api.test.js

Confirm that the execution result of the above command matches the following.

{ actual: { ok: true }, expected: { ok: true } }
OK getApiStatusTest

Conclusion

While axios is a well-known library for sending HTTP requests, fetch is the standard API for front-end JavaScript. By installing node-fetch and making fetch available in Node.js, you can reduce the amount of memorization.

Compared to unit tests and UI tests, API tests can handle database access, etc., and test code is easy to write, so it is more useful than the other two. When doing API testing, it is useful to be able to initialize the database when needed.

Some web apps require authentication or authorization to access the API. If you're using OAuth 2.0 and can use Client Credentials Grant, it's not too much of a hassle as it only adds to the effort of getting an access token such as JWT from an authorization endpoint such as Auth0. On the other hand, if you use cookies for authentication, it's a bit annoying. I manually log in with a web browser, then use developer tools to find and copy the cookie and pass it using environment variables etc. when running the test code. This method is tedious and not secure, so if anyone knows a good way, I would appreciate your guidance and comments. Other comments are welcome. Thank you for reading!

Related articles

/node_modules/
/package-lock.json
# Do not ignore package-lock.json other than gist.
const express = require('express')
if (require.main === module) {
main()
}
async function main () {
try {
const router = express()
router.get('/api/status', (req, res) => {
res.send({ok: true})
})
const port = parseInt(process.env.PORT || '3000', 10)
router.listen(port, () => {
console.info(`Listening on ${port}`)
})
} catch (err) {
console.error(err)
}
}
const assert = require('assert')
const fetch = require('node-fetch') // <1>
if (require.main === module) {
main()
}
async function main () {
try {
const tests = [
getApiStatusTest,
]
for (const test of tests) {
try {
await test()
console.info(`OK ${test.name}`)
} catch (err) {
console.info(`NG ${test.name}`)
console.error(err)
}
}
} catch (err) {
console.error(err)
}
}
async function getApiStatusTest () {
const method = 'GET'
const url = 'http://localhost:3000/api/status'
const response = await fetch(url, {method}) // <2>
const actual = await response.json()
const expected = {ok: true}
assert.strictEqual(response.status, 200) // <3>
assert.deepStrictEqual(actual, expected) // <4>
console.info({actual, expected})
}
{
"name": "nodejs-test-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"node-fetch": "^2.6.7"
},
"dependencies": {
"express": "^4.18.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment