Let’s into a fresh directory called ‘testing-example’ and type npm init -y in our terminal.

    Run npm install fastify && npm install tap pino-pretty --save-dev

    First, we are going to separate our application code from our server code:

    app.js:

    server.js:

    1. 'use strict'
    2. const server = require('./app')({
    3. logger: {
    4. level: 'info',
    5. prettyPrint: true
    6. }
    7. })
    8. server.listen(3000, (err, address) => {
    9. if (err) {
    10. console.log(err)
    11. process.exit(1)
    12. }
    13. })

    Fastify comes with built-in support for fake HTTP injection thanks to .

    Before introducing any tests, we will use the .inject method to make a fake request to our route:

    app.test.js:

    1. 'use strict'
    2. const build = require('./app')
    3. const test = async () => {
    4. const app = build()
    5. const response = await app.inject({
    6. method: 'GET',
    7. url: '/'
    8. })
    9. console.log('status code: ', response.statusCode)
    10. console.log('body: ', response.body)
    11. }
    12. test()

    First, our code will run inside an asynchronous function, giving us access to async/await.

    Run the test file in your terminal node app.test.js

    1. status code: 200
    2. body: {"hello":"world"}

    Now we can replace our console.log calls with actual tests!

    In your package.json change the “test” script to:

    "test": "tap --reporter=list --watch"

    app.test.js:

    1. 'use strict'
    2. const { test } = require('tap')
    3. const build = require('./app')
    4. test('requests the "/" route', async t => {
    5. const app = build()
    6. method: 'GET',
    7. })
    8. t.equal(response.statusCode, 200, 'returns a status code of 200')
    9. })

    Finally, run npm test in the terminal and see your test results!

    The inject method can do much more than a simple GET request to a URL:

    .inject methods can also be chained by omitting the callback function:

    1. fastify
    2. .inject()
    3. .get('/')
    4. .headers({ foo: 'bar' })
    5. .query({ foo: 'bar' })
    6. .end((err, res) => { // the .end call will trigger the request
    7. console.log(res.payload)
    8. })

    or in the promisified version

    1. fastify
    2. .inject({
    3. method: String,
    4. url: String,
    5. query: Object,
    6. payload: Object,
    7. headers: Object,
    8. cookies: Object
    9. })
    10. .then(response => {
    11. // your tests
    12. })
    13. .catch(err => {
    14. // handle error
    15. })
    1. try {
    2. const res = await fastify.inject({ method: String, url: String, payload: Object, headers: Object })
    3. // your tests
    4. } catch (err) {
    5. // handle error
    6. }

    Another Example:

    app.js

    1. const Fastify = require('fastify')
    2. function buildFastify () {
    3. const fastify = Fastify()
    4. fastify.get('/', function (request, reply) {
    5. reply.send({ hello: 'world' })
    6. })
    7. return fastify
    8. }
    9. module.exports = buildFastify

    test.js

    Fastify can also be tested after starting the server with fastify.listen() or after initializing routes and plugins with fastify.ready().

    Example:

    Uses app.js from the previous example.

    test-listen.js (testing with Request)

    1. const tap = require('tap')
    2. const buildFastify = require('./app')
    3. tap.test('GET `/` route', t => {
    4. t.plan(5)
    5. const fastify = buildFastify()
    6. t.teardown(() => fastify.close())
    7. fastify.listen(0, (err) => {
    8. t.error(err)
    9. request({
    10. method: 'GET',
    11. url: 'http://localhost:' + fastify.server.address().port
    12. }, (err, response, body) => {
    13. t.error(err)
    14. t.equal(response.statusCode, 200)
    15. t.equal(response.headers['content-type'], 'application/json; charset=utf-8')
    16. t.same(JSON.parse(body), { hello: 'world' })
    17. })
    18. })
    19. })

    test-ready.js (testing with )

    1. const tap = require('tap')
    2. const supertest = require('supertest')
    3. const buildFastify = require('./app')
    4. tap.test('GET `/` route', async (t) => {
    5. const fastify = buildFastify()
    6. t.teardown(() => fastify.close())
    7. await fastify.ready()
    8. const response = await supertest(fastify.server)
    9. .get('/')
    10. .expect(200)
    11. .expect('Content-Type', 'application/json; charset=utf-8')
    12. t.same(response.body, { hello: 'world' })
    13. })
    1. Isolate your test by passing the {only: true} option

      1. test('should ...', {only: true}, t => ...)
    2. Run tap using npx

      1. > npx tap -O -T --node-arg=--inspect-brk test/<test-file.test.js>
    • -O specifies to run tests with the only option enabled
    • -T specifies not to timeout (while you’re debugging)
    • --node-arg=--inspect-brk will launch the node debugger
    1. In VS Code, create and launch a Node.js: Attach debug configuration. No modification should be necessary.

    Now you should be able to step through your test file (and the rest of Fastify) in your code editor.