Chris H
Chris H

Reputation: 511

How to startup the server when testing an Express app via Mocha

I would like to write unit tests using Mocha for my Nodejs/Express app that I have written in visual studio. I have scoured everywhere I could looking for a simple tutorial but not found what I am looking for. I have seen many tutorials in creating a test using assert to test that 5=5, etc. but that's not what I want to do.

I am trying to add a JavaScript Mocha Unit Test file through VS and then all I really want it to do is open the home page of my app, check for some content in the body and pass the test. If I want to run the tests from the Test Explorer window the nodejs app can't be running and if it isn't running there would be nothing to receive the request for the homepage.

So I'm not sure if the test itself is somehow supposed to launch the app or what? I feel like I'm in a catch 22 and missing the very basics, just don't see it described anywhere.

Upvotes: 4

Views: 2852

Answers (1)

nicholaswmin
nicholaswmin

Reputation: 22989

What you're looking for is most commonly called an API test - a part of integration testing, not a unit test. If a test touches network, a database or I/O it's, most commonly, an integration test instead.

Now to your question. In order to test your app.js code without starting up the server manually beforehand you can do the following:

  • module.export your app server.
  • In your tests, use chai-http to test routes.
  • require your app in the tests and use that instead of URL's when testing routes.

The key here is the 1st bullet point. You must export your app so you can require it and use it in your tests. This allows you to skip the part where you start a separate server process to run the tests on.

Server code

// app.js

const express = require('express')
const app = express()
const bodyParser = require('body-parser')

app.use(bodyParser.json())

// Routes

app.post('/register', (req, res) => {
  const requiredFields = ['name', 'email']

  if (requiredFields.every(field => Object.keys(req.body).includes(field))) {
    // Run business logic and insert user in DB ...
    res.sendStatus(204)
  } else {
    res.sendStatus(400)
  }
})

app.listen(3000)

// export your app so you can include it in your tests.
module.exports = app

Test code

// test/registration.spec.js
const chai = require('chai')
const chaiHttp = require('chai-http')
// `require` your exported `app`.
const app = require('../app.js')

chai.should()
chai.use(chaiHttp)

describe('User registration', () => {
  it('responds with HTTP 204 if form fields are valid', () => {
    return chai.request(app)
      .post('/register')
      .send({
        name: 'John Doe',
        email: '[email protected]'
      })
      .then(res => {
        res.should.have.status(204)
      })
      .catch(err => {
        throw err
      })
  })

  it('responds with HTTP 400 if some fields are missing', () => {
    return chai.request(app)
      .post('/register')
      .send({
        name: 'John Doe'
      })
      .catch(err => {
        err.should.have.status(400)
      })
  })
})

Then just run your test from the root directory with:

$ mocha test/registration.spec.js

Upvotes: 4

Related Questions