Testing secure endpoints with integration testing
Tags: testing, node, javascript
Published: 2021-06-26 13:08:41

---
title: Testing secure endpoints with integration testing
published: true
date: 2021-05-26 12:53:03 UTC
tags: testing,nodejs,javascript
canonical_url: https://hyper-io.medium.com/testing-secure-endpoints-with-integration-testing-6ebd61ee9d2b
---

Testing APIs is a non-functional requirement for successful APIs, it is part of the definition of done. Securing APIs is also a non-functional requirement.

Creating an integration test on a secure endpoint that uses session-based secure cookies can be a challenge! This post will step through the approach we took to create these integration tests even while secured by session-based cookies.

> Integration Tests are test that verify a collection of components properly work together to perform a process. A common integration test is from the API Endpoint to the Service Layer.

{% youtube AwmVpag0uu4 %}

Here is our server setup:

server.js

```
const express = require('express')
const session = require('express-session')
const app = express()
const auth = require('./middleware/auth')

app.use(session({
  secret: 'jack russell',
  resave: false,
  saveUinitialized: true,
  cookie: { secure: true }
}))

app.use(auth.check)

app.post('/login', (req, res) => {
  req.session.user = { name: req.query.name }
  res.status(201).json({ ok: true })
})

app.get('/movies', (req, res) => {
  res.status(200).json(['Ghostbusters', 'Grounhog Day', 'What about Bob?', 'Stripes', 'Caddyshack'])
})

app.get('/logout', (req, res) => {
  res.session.user = null
  res.json({ ok: true })
})

if (!module.parent) {
  app.listen(3000)
}

module.exports = app
```

middleware/auth.js

```
exports.check = function (req, res, next) {
  if (req.path !== '/login' && req.session.user) {
    next()
  } else {
    res.status(401).json({ message: 'not authorized' })
  }
}
```

So we have a very simple API that returns a list of movies, but you have to be logged in to the API to get the movies’ list.

Let’s write a test!

test/movies.js

```
const test = require('tape')
const testServer = require('@twilson63/test-server')
const fetch = require('node-fetch')

const app = require('../server')

test('List Movies', async (t) => {
  t.plan(1)
  const server = testServer(app)
  const result = await fetch(server.url + '/movies').then(r => r.json())
  t.deepEqual(result, ['Ghostbusters', 'Grounhog Day', 'What about Bob?', 'Stripes', 'Caddyshack'])

  server.close()
})
```

Great! Our test is simple, but it should serve our purpose. Let’s give it a run:

node test/movies\_test.js

```
not ok 1 should be strictly equal
  ---
    operator: equal
    expected: |-
      ['Ghostbusters', 'Grounhog Day', 'What about Bob?', 'Stripes', 'Caddyshack']
    actual: |-
      { message: 'not authorized' }
```

#### Oops, what is the problem?

So we can’t test our endpoint, because it is secured, so how do we work around this issue? We can use sinon 's stub feature.

```
const test = require('tape')
const testServer = require('@twilson63/test-server')
const fetch = require('node-fetch')
const sinon = require('sinon')

const auth = require('../middleware/auth')
sinon.stub(auth, 'check').callsFake(function (req, res, next) {
  req.user = 'bob'
  next()
})

const app = require('../server')

test('List Movies', async (t) => {
  t.plan(1)
  const server = testServer(app)
  const result = await fetch(server.url + '/movies').then(r => r.json())
  t.deepEqual(result, ['Ghostbusters', 'Grounhog Day', 'What about Bob?', 'Stripes', 'Caddyshack'])

  server.close()
})
```

The result

```
TAP version 13
# List Movies
ok 1 should be deeply equivalent

1..1
# tests 1
# pass 1

# ok
```

#### What is sinon.js?

Sinon is a standalone mocking library that enables you to spy, stub, and mock code for your application, you can check it out at [https://sinonjs.org/](https://sinonjs.org/) — I would recommend not to overuse Sinon, but it can come in handy for issues like this one.

#### Summary

Testing around security can be tricky mocking tools like sinon come in handy to create tests that focus on testing your code.

The full example is available here: [https://github.com/hyper63/testing-secure-endpoints](https://github.com/hyper63/testing-secure-endpoints)