1 | <h1 align="center">Fastify</h1>
|
2 |
|
3 | ## Testing
|
4 | Testing is one of the most important parts of developing an application. Fastify is very flexible when it comes to testing and is compatible with most testing frameworks (such as [Tap](https://www.npmjs.com/package/tap), which is used in the examples below).
|
5 |
|
6 | <a name="inject"></a>
|
7 | ### Testing with http injection
|
8 | Fastify comes with built-in support for fake http injection thanks to [`light-my-request`](https://github.com/fastify/light-my-request).
|
9 |
|
10 | To inject a fake http request, use the `inject` method:
|
11 | ```js
|
12 | fastify.inject({
|
13 | method: String,
|
14 | url: String,
|
15 | query: Object,
|
16 | payload: Object,
|
17 | headers: Object,
|
18 | cookies: Object
|
19 | }, (error, response) => {
|
20 | // your tests
|
21 | })
|
22 | ```
|
23 |
|
24 | `.inject` methods can also be chained by omitting the callback function:
|
25 |
|
26 | ```js
|
27 | fastify
|
28 | .inject()
|
29 | .get('/')
|
30 | .headers({ foo: 'bar' })
|
31 | .query({ foo: 'bar' })
|
32 | .end((err, res) => { // the .end call will trigger the request
|
33 | console.log(res.payload)
|
34 | })
|
35 | ```
|
36 |
|
37 | or in the promisified version
|
38 |
|
39 | ```js
|
40 | fastify
|
41 | .inject({
|
42 | method: String,
|
43 | url: String,
|
44 | query: Object,
|
45 | payload: Object,
|
46 | headers: Object,
|
47 | cookies: Object
|
48 | })
|
49 | .then(response => {
|
50 | // your tests
|
51 | })
|
52 | .catch(err => {
|
53 | // handle error
|
54 | })
|
55 | ```
|
56 |
|
57 | Async await is supported as well!
|
58 | ```js
|
59 | try {
|
60 | const res = await fastify.inject({ method: String, url: String, payload: Object, headers: Object })
|
61 | // your tests
|
62 | } catch (err) {
|
63 | // handle error
|
64 | }
|
65 | ```
|
66 |
|
67 | #### Example:
|
68 |
|
69 | **app.js**
|
70 | ```js
|
71 | const Fastify = require('fastify')
|
72 |
|
73 | function buildFastify () {
|
74 | const fastify = Fastify()
|
75 |
|
76 | fastify.get('/', function (request, reply) {
|
77 | reply.send({ hello: 'world' })
|
78 | })
|
79 |
|
80 | return fastify
|
81 | }
|
82 |
|
83 | module.exports = buildFastify
|
84 | ```
|
85 |
|
86 | **test.js**
|
87 | ```js
|
88 | const tap = require('tap')
|
89 | const buildFastify = require('./app')
|
90 |
|
91 | tap.test('GET `/` route', t => {
|
92 | t.plan(4)
|
93 |
|
94 | const fastify = buildFastify()
|
95 |
|
96 | // At the end of your tests it is highly recommended to call `.close()`
|
97 | // to ensure that all connections to external services get closed.
|
98 | t.tearDown(() => fastify.close())
|
99 |
|
100 | fastify.inject({
|
101 | method: 'GET',
|
102 | url: '/'
|
103 | }, (err, response) => {
|
104 | t.error(err)
|
105 | t.strictEqual(response.statusCode, 200)
|
106 | t.strictEqual(response.headers['content-type'], 'application/json; charset=utf-8')
|
107 | t.deepEqual(response.json(), { hello: 'world' })
|
108 | })
|
109 | })
|
110 | ```
|
111 |
|
112 | ### Testing with a running server
|
113 | Fastify can also be tested after starting the server with `fastify.listen()` or after initializing routes and plugins with `fastify.ready()`.
|
114 |
|
115 | #### Example:
|
116 |
|
117 | Uses **app.js** from the previous example.
|
118 |
|
119 | **test-listen.js** (testing with [`Request`](https://www.npmjs.com/package/request))
|
120 | ```js
|
121 | const tap = require('tap')
|
122 | const request = require('request')
|
123 | const buildFastify = require('./app')
|
124 |
|
125 | tap.test('GET `/` route', t => {
|
126 | t.plan(5)
|
127 |
|
128 | const fastify = buildFastify()
|
129 |
|
130 | t.tearDown(() => fastify.close())
|
131 |
|
132 | fastify.listen(0, (err) => {
|
133 | t.error(err)
|
134 |
|
135 | request({
|
136 | method: 'GET',
|
137 | url: 'http://localhost:' + fastify.server.address().port
|
138 | }, (err, response, body) => {
|
139 | t.error(err)
|
140 | t.strictEqual(response.statusCode, 200)
|
141 | t.strictEqual(response.headers['content-type'], 'application/json; charset=utf-8')
|
142 | t.deepEqual(JSON.parse(body), { hello: 'world' })
|
143 | })
|
144 | })
|
145 | })
|
146 | ```
|
147 |
|
148 | **test-ready.js** (testing with [`SuperTest`](https://www.npmjs.com/package/supertest))
|
149 | ```js
|
150 | const tap = require('tap')
|
151 | const supertest = require('supertest')
|
152 | const buildFastify = require('./app')
|
153 |
|
154 | tap.test('GET `/` route', async (t) => {
|
155 | const fastify = buildFastify()
|
156 |
|
157 | t.tearDown(() => fastify.close())
|
158 |
|
159 | await fastify.ready()
|
160 |
|
161 | const response = await supertest(fastify.server)
|
162 | .get('/')
|
163 | .expect(200)
|
164 | .expect('Content-Type', 'application/json; charset=utf-8')
|
165 | t.deepEqual(response.body, { hello: 'world' })
|
166 | })
|
167 | ```
|
168 |
|
169 | ### How to inspect tap tests
|
170 | 1. Isolate your test by passing the `{only: true}` option
|
171 | ```javascript
|
172 | test('should ...', {only: true}, t => ...)
|
173 | ```
|
174 | 2. Run `tap` using `npx`
|
175 | ```bash
|
176 | > npx tap -O -T --node-arg=--inspect-brk test/<test-file.test.js>
|
177 | ```
|
178 | - `-O` specifies to run tests with the `only` option enabled
|
179 | - `-T` specifies not to timeout (while you're debugging)
|
180 | - `--node-arg=--inspect-brk` will launch the node debugger
|
181 | 3. In VS Code, create and launch a `Node.js: Attach` debug configuration. No modification should be necessary.
|
182 |
|
183 | Now you should be able to step through your test file (and the rest of `fastify`) in your code editor.
|