I'm new in Jest and TDD. Please, help me! I'm using supertest to request the API, but even with the server turned off, the tests never fail. I've tried use return or async await and it not solved
I have the following structure at Node.js project:
nodemodules
src
controllers
users-controller.js
index.js
routes.js
server.js
test
user.test.js
package.json
package.json:
"scripts": {
"test": "jest",
"lint": "eslint src/** test/** --fix",
"start": "node src/server.js",
"jest-watch": "jest --watch"
},
"devDependencies": {
"eslint": "^6.8.0",
"jest": "^25.3.0",
"supertest": "^4.0.2"
},
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1"
}
src/server.js:
const app = require('./index')
app.listen(3001, () => {
console.log('Server running on port 3001')
})
src/index.js:
const express = require('express')
const routes = require('./routes')
const app = express()
app.use(express.json())
app.use(routes)
module.exports = app
src/routes.js
const routes = require('express').Router()
const UserController = require('./controllers/users-controller')
routes.get('/', (req, res) => { res.status(200).send() })
routes.get('/users', UserController.findAll)
routes.post('/users', UserController.create)
module.exports = routes
src/controllers/user-controller.js
module.exports = {
findAll(req, res) {
const users = [
{ name: 'John Doe', mail: '[email protected]' }
]
return res.status(200).json(users)
},
create(req, res) {
return res.status(201).json(req.body)
}
}}
test/user.test.js:
const request = require('supertest')
const app = require('../src/index')
test('Should list users', () => {
return request(app).get('/users')
.then(res => {
expect(res.status).toBe(200)
expect(res.body).toHaveLength(1)
expect(res.body[0]).toHaveProperty('name', 'John Doe')
})
})
test('Should insert a user', async () => {
await request(app).post('/users')
.send({ name: 'Walter Mitty', email: '[email protected]' })
.then(res => {
expect(res.status).toBe(201)
expect(res.body.name).toBe('Walter Mitty')
})
})
And the result is always the same:
PASS test / user.test.js
✓ Should list users. (16ms)
✓ Should insert a user. (13ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 0.456s, estimated 1s
Ran all test suites related to changed files.
Watch Usage: Press w to show more.
Oh I see what the problem is, although isn't really a problem, is the normal behavior of Jest and Supertest. I'll explain to you. If Express app isn't listening, it doesn't affect the Jest or Supertest behavior. Why? Just because the app
that you pass to supertest request(app)
runs an independent process of the app, and when the tests are finished, that app finishes too. In other words, Supertest runs the Express app on a different process, do the tests, and finishes that process.
This test will fail if you expect another response code, for example 400. The following test should fail for sure:
test('Should list users', async () => {
// First assertion
const response = await request(app)
.get('/users')
.send()
.expect(400) // This will make fail, because the app instance running for test, is working just fine and will return 200, if you expect a different code, so the test will fail
// Second assertion
expect(response.body[0]).toHaveProperty('name', 'John Doe')
})
So that is the normal behavior of Jest and Supertest. It runs the Express app, just for running the tests, in another independent process. It doesn't matter if your Express main process is still running or if it's stopped.