Shamoon
Shamoon

Reputation: 43491

How to set up code coverage and unit tests for express functions?

I have a route defined like

app.post '/v1/media', authentication.hasValidApiKey, multipart, mediaController.create, mediaController.get

I want to write tests for the individual components of the route. So starting with authentication.hasValidApiKey, that's a function defined in another file:

exports.hasTokenOrApi = (req, res, next) ->
  if not req.headers.authorization
    return res.status(403).end()

  doOtherStuff...

In my test, I have:

authentication = require '../src/middlewares/authentication'

describe 'Authentication Middleware', ->
  before (done) ->
    done()

  it 'should check for authentication', (done) ->
    mock_req = null
    mock_res = null
    mock_next = null

    authentication.hasTokenOrApi mock_res, mock_req, mock_next
    done()

How do I deal with the req, res and next? And how can I setup code coverage to run? I am running my tests with: export NODE_ENV=test && ./node_modules/.bin/mocha --compilers coffee:'./node_modules/coffee-script/lib/coffee-script/register'

Upvotes: 1

Views: 1214

Answers (1)

Justin Maat
Justin Maat

Reputation: 1975

There are multiple code coverage tools, many with integrations in different build systems (gulp, grunt, etc..).

One of the leading one's is Istanbul which is what I personally use. Other popular libraries are blankets and coveralls

To see an example setup using Gulp and Istanbul (and mocha), check out this gist I have

Basically, you can just run through your test directory, pipe each test file through istanbul, then mocha, and have a coverage report generated if desired.

gulp.src(['test/**/*.js'])
    .pipe(istanbul({includeUntested: true})) // Covering files
    .pipe(istanbul.hookRequire()) // Force `require` to return covered files
    .on('finish', function () {
        gulp.src(['test/**/*.js'])
            .pipe(mocha())
            .pipe(istanbul.writeReports(
                {
                    dir: './coverage',
                    reporters: ['html', 'lcov', 'json', 'text', 'text-summary', 'cobertura']
                })) // Creating the reports after tests runned
            .on('end', cb);
    });

In regards to how to test just the Routing (assuming it's decoupled in a separate file or module), this can be kind of tricky. I have similar questions posted here and here.

But essentially what you're asking in the above code calls for a stub of req and a spy of res.status(403).end(). The spy can be a bit tricky because you basically need to spy on the actual Response object in express (can google around their docs to see how to get it).

If you're not already familiar, I'd suggest using sinon , but there's also other libraries for mock/stub/spies.

It seems many in the community just use Supertest and call it a day, but to me that would make it an integration test. A true unit test would make you isolate the specific section you're trying to test.

Upvotes: 2

Related Questions