├── .dockerignore
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── Dockerfile
├── Makefile
├── README.md
├── docker-compose.yml
├── index.js
├── my-test-framework
├── expect.js
├── spy.js
└── test.js
├── package-lock.json
├── package.json
├── src
├── thumb-war.js
└── utils.js
└── tests
├── __mocks__
└── utils.js
├── external-mock-module.test.js
└── spy.test.js
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Continuous Integration
2 |
3 | on:
4 | push:
5 | workflow_dispatch:
6 |
7 | jobs:
8 | test:
9 |
10 | runs-on: ubuntu-18.04
11 |
12 | steps:
13 | - name: Project checkout
14 | uses: actions/checkout@v2
15 | - run: docker-compose build test
16 | - name: Run tests
17 | run: make test
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 |
2 | FROM node:lts-alpine3.12
3 |
4 | WORKDIR /app
5 |
6 | COPY package*.json ./
7 |
8 | RUN npm ci
9 |
10 | COPY . .
11 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: test
2 |
3 | test:
4 | @docker-compose run test
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Fundamento de funcionamento de spy e mock externo
2 |
3 |
4 |
Esse material é quase de graça, basta deixar uma star ⭐ no repositório.
5 |
6 |
7 |
8 | Esse material consiste em entender o funcionamento interno de:
9 | 1. **mock de uma dependência**, substituindo seu conteúdo pelo arquivo de mesmo nome no diretório `__mocks__`
10 | 1. **spy**, entendendo como altera o conteúdo ao mesmo tempo que armazena o conteúdo das chamadas feitas.
11 | 1. **test**, sendo a estrutura, aonde os testes estão inseridos.
12 | 1. **expect**, realizando comparação do valor esperado com o atual.
13 |
14 | O material foi implementado dentro do diretório [my-test-framework](./my-test-framework), enquanto os testes estão em [tests](./tests), validando o comportamento do método `thumbWar`, que está em [src](./src).
15 |
16 | Acesse:
17 | 1. A [implementação do spy](./my-test-framework/spy.js) e o [teste que consome o spy](./tests/spy.test.js) para entender o funcionamento de um Spy e como armazena todas as chamadas feitas e argumentos passados.
18 | 1. O [teste mockando com módulo externo](./tests/external-mock-module.test.js) e o [novo comportamento do método getWinner](./tests/__mocks__/utils.js) para entender como é alterado o comportamento de um módulo através de cache.
19 |
20 |
21 |
22 |
23 |
24 | ## Execução
25 |
26 | ### Com docker e docker-compose
27 |
28 | ```
29 | make test
30 | ```
31 |
32 | ### Com node
33 |
34 | 1. Instale as dependências:
35 | ```
36 | npm install
37 | ```
38 |
39 | > As únicas dependências são utilizadas apenas na exibição do resultado no terminal
40 |
41 | 2. Execute o seguinte comando para executar os testes:
42 |
43 | ```
44 | npm test
45 | ```
46 | ou
47 | ```
48 | node index.js ./**/*.test.js
49 | ```
50 |
51 | ## Materiais
52 |
53 | - [require.cache](https://nodejs.org/api/modules.html#modules_require_cache): Utilizado para alterar o módulo carregado em cache.
54 | - [require.resolve](https://nodejs.org/api/modules.html#modules_require_resolve_request_options): Utilizado para pegar a localização do módulo.
55 |
56 | ## Extra
57 |
58 | Repositório: [Material de estudo de testes de unidade e dublês de teste utilizando Jest](https://github.com/PauloGoncalvesBH/dubles-de-teste-com-jest)
59 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.8'
2 |
3 | services:
4 | test:
5 | build:
6 | context: .
7 | dockerfile: ./Dockerfile
8 | command: npm test
9 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | global.test = require('./my-test-framework/test').test
2 | global.expect = require('./my-test-framework/expect')
3 |
4 | module.exports = {
5 | spyOn: require('./my-test-framework/spy').spyOn,
6 | }
7 |
8 | const files = process.argv
9 | files.slice(2).forEach((file) => require(file))
10 |
--------------------------------------------------------------------------------
/my-test-framework/expect.js:
--------------------------------------------------------------------------------
1 | const chalk = require('chalk')
2 |
3 | const actualMessage = msg => chalk.green.bold(msg)
4 | const expectedMessage = msg => chalk.red.bold(msg)
5 | const errorMessage = (actual, expected) => `${actualMessage(actual)} is not equal to ${expectedMessage(expected)}`
6 |
7 | function expect(actual) {
8 | return {
9 | toBe(expected) {
10 | if (actual !== expected) {
11 | throw new Error(errorMessage(actual, expected))
12 | }
13 | },
14 | toBeDeepStrictEqual(expected) {
15 | if (JSON.stringify(actual) !== JSON.stringify(expected)) {
16 | throw new Error(errorMessage(actual, expected))
17 | }
18 | },
19 | }
20 | }
21 |
22 | module.exports = expect
23 |
--------------------------------------------------------------------------------
/my-test-framework/spy.js:
--------------------------------------------------------------------------------
1 | function fn(impl = () => {}) {
2 | const mockFn = (...args) => {
3 | mockFn.mock.calls.push(args)
4 | return impl(...args)
5 | }
6 | mockFn.mock = {calls: []}
7 | mockFn.mockImplementation = newImpl => (impl = newImpl)
8 | return mockFn
9 | }
10 |
11 | function spyOn(obj, prop) {
12 | const originalValue = obj[prop]
13 | obj[prop] = fn()
14 | obj[prop].mockRestore = () => (obj[prop] = originalValue)
15 | }
16 |
17 | module.exports = { spyOn }
18 |
--------------------------------------------------------------------------------
/my-test-framework/test.js:
--------------------------------------------------------------------------------
1 | const signale = require('signale')
2 |
3 | async function test(title, callback) {
4 | try {
5 | await callback()
6 | signale.success(title)
7 | } catch (error) {
8 | signale.error(title)
9 | console.error(error)
10 | process.exit(1)
11 | }
12 | }
13 |
14 | module.exports = { test }
15 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-test-framework",
3 | "version": "1.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "my-test-framework",
9 | "version": "1.0.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "chalk": "2.4.2",
13 | "signale": "1.4.0"
14 | }
15 | },
16 | "node_modules/ansi-styles": {
17 | "version": "3.2.1",
18 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
19 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
20 | "dependencies": {
21 | "color-convert": "^1.9.0"
22 | },
23 | "engines": {
24 | "node": ">=4"
25 | }
26 | },
27 | "node_modules/chalk": {
28 | "version": "2.4.2",
29 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
30 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
31 | "dependencies": {
32 | "ansi-styles": "^3.2.1",
33 | "escape-string-regexp": "^1.0.5",
34 | "supports-color": "^5.3.0"
35 | },
36 | "engines": {
37 | "node": ">=4"
38 | }
39 | },
40 | "node_modules/color-convert": {
41 | "version": "1.9.3",
42 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
43 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
44 | "dependencies": {
45 | "color-name": "1.1.3"
46 | }
47 | },
48 | "node_modules/color-name": {
49 | "version": "1.1.3",
50 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
51 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
52 | },
53 | "node_modules/error-ex": {
54 | "version": "1.3.2",
55 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
56 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
57 | "dependencies": {
58 | "is-arrayish": "^0.2.1"
59 | }
60 | },
61 | "node_modules/escape-string-regexp": {
62 | "version": "1.0.5",
63 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
64 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
65 | "engines": {
66 | "node": ">=0.8.0"
67 | }
68 | },
69 | "node_modules/figures": {
70 | "version": "2.0.0",
71 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
72 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
73 | "dependencies": {
74 | "escape-string-regexp": "^1.0.5"
75 | },
76 | "engines": {
77 | "node": ">=4"
78 | }
79 | },
80 | "node_modules/find-up": {
81 | "version": "2.1.0",
82 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
83 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
84 | "dependencies": {
85 | "locate-path": "^2.0.0"
86 | },
87 | "engines": {
88 | "node": ">=4"
89 | }
90 | },
91 | "node_modules/graceful-fs": {
92 | "version": "4.2.6",
93 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
94 | "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
95 | },
96 | "node_modules/has-flag": {
97 | "version": "3.0.0",
98 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
99 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
100 | "engines": {
101 | "node": ">=4"
102 | }
103 | },
104 | "node_modules/is-arrayish": {
105 | "version": "0.2.1",
106 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
107 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
108 | },
109 | "node_modules/json-parse-better-errors": {
110 | "version": "1.0.2",
111 | "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
112 | "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
113 | },
114 | "node_modules/load-json-file": {
115 | "version": "4.0.0",
116 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
117 | "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
118 | "dependencies": {
119 | "graceful-fs": "^4.1.2",
120 | "parse-json": "^4.0.0",
121 | "pify": "^3.0.0",
122 | "strip-bom": "^3.0.0"
123 | },
124 | "engines": {
125 | "node": ">=4"
126 | }
127 | },
128 | "node_modules/locate-path": {
129 | "version": "2.0.0",
130 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
131 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
132 | "dependencies": {
133 | "p-locate": "^2.0.0",
134 | "path-exists": "^3.0.0"
135 | },
136 | "engines": {
137 | "node": ">=4"
138 | }
139 | },
140 | "node_modules/p-limit": {
141 | "version": "1.3.0",
142 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
143 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
144 | "dependencies": {
145 | "p-try": "^1.0.0"
146 | },
147 | "engines": {
148 | "node": ">=4"
149 | }
150 | },
151 | "node_modules/p-locate": {
152 | "version": "2.0.0",
153 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
154 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
155 | "dependencies": {
156 | "p-limit": "^1.1.0"
157 | },
158 | "engines": {
159 | "node": ">=4"
160 | }
161 | },
162 | "node_modules/p-try": {
163 | "version": "1.0.0",
164 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
165 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
166 | "engines": {
167 | "node": ">=4"
168 | }
169 | },
170 | "node_modules/parse-json": {
171 | "version": "4.0.0",
172 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
173 | "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
174 | "dependencies": {
175 | "error-ex": "^1.3.1",
176 | "json-parse-better-errors": "^1.0.1"
177 | },
178 | "engines": {
179 | "node": ">=4"
180 | }
181 | },
182 | "node_modules/path-exists": {
183 | "version": "3.0.0",
184 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
185 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
186 | "engines": {
187 | "node": ">=4"
188 | }
189 | },
190 | "node_modules/pify": {
191 | "version": "3.0.0",
192 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
193 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
194 | "engines": {
195 | "node": ">=4"
196 | }
197 | },
198 | "node_modules/pkg-conf": {
199 | "version": "2.1.0",
200 | "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz",
201 | "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=",
202 | "dependencies": {
203 | "find-up": "^2.0.0",
204 | "load-json-file": "^4.0.0"
205 | },
206 | "engines": {
207 | "node": ">=4"
208 | }
209 | },
210 | "node_modules/signale": {
211 | "version": "1.4.0",
212 | "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz",
213 | "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==",
214 | "dependencies": {
215 | "chalk": "^2.3.2",
216 | "figures": "^2.0.0",
217 | "pkg-conf": "^2.1.0"
218 | },
219 | "engines": {
220 | "node": ">=6"
221 | }
222 | },
223 | "node_modules/strip-bom": {
224 | "version": "3.0.0",
225 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
226 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
227 | "engines": {
228 | "node": ">=4"
229 | }
230 | },
231 | "node_modules/supports-color": {
232 | "version": "5.5.0",
233 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
234 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
235 | "dependencies": {
236 | "has-flag": "^3.0.0"
237 | },
238 | "engines": {
239 | "node": ">=4"
240 | }
241 | }
242 | },
243 | "dependencies": {
244 | "ansi-styles": {
245 | "version": "3.2.1",
246 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
247 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
248 | "requires": {
249 | "color-convert": "^1.9.0"
250 | }
251 | },
252 | "chalk": {
253 | "version": "2.4.2",
254 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
255 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
256 | "requires": {
257 | "ansi-styles": "^3.2.1",
258 | "escape-string-regexp": "^1.0.5",
259 | "supports-color": "^5.3.0"
260 | }
261 | },
262 | "color-convert": {
263 | "version": "1.9.3",
264 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
265 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
266 | "requires": {
267 | "color-name": "1.1.3"
268 | }
269 | },
270 | "color-name": {
271 | "version": "1.1.3",
272 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
273 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
274 | },
275 | "error-ex": {
276 | "version": "1.3.2",
277 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
278 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
279 | "requires": {
280 | "is-arrayish": "^0.2.1"
281 | }
282 | },
283 | "escape-string-regexp": {
284 | "version": "1.0.5",
285 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
286 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
287 | },
288 | "figures": {
289 | "version": "2.0.0",
290 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
291 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
292 | "requires": {
293 | "escape-string-regexp": "^1.0.5"
294 | }
295 | },
296 | "find-up": {
297 | "version": "2.1.0",
298 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
299 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
300 | "requires": {
301 | "locate-path": "^2.0.0"
302 | }
303 | },
304 | "graceful-fs": {
305 | "version": "4.2.6",
306 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz",
307 | "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ=="
308 | },
309 | "has-flag": {
310 | "version": "3.0.0",
311 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
312 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
313 | },
314 | "is-arrayish": {
315 | "version": "0.2.1",
316 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
317 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
318 | },
319 | "json-parse-better-errors": {
320 | "version": "1.0.2",
321 | "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
322 | "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
323 | },
324 | "load-json-file": {
325 | "version": "4.0.0",
326 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
327 | "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
328 | "requires": {
329 | "graceful-fs": "^4.1.2",
330 | "parse-json": "^4.0.0",
331 | "pify": "^3.0.0",
332 | "strip-bom": "^3.0.0"
333 | }
334 | },
335 | "locate-path": {
336 | "version": "2.0.0",
337 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
338 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
339 | "requires": {
340 | "p-locate": "^2.0.0",
341 | "path-exists": "^3.0.0"
342 | }
343 | },
344 | "p-limit": {
345 | "version": "1.3.0",
346 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
347 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
348 | "requires": {
349 | "p-try": "^1.0.0"
350 | }
351 | },
352 | "p-locate": {
353 | "version": "2.0.0",
354 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
355 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
356 | "requires": {
357 | "p-limit": "^1.1.0"
358 | }
359 | },
360 | "p-try": {
361 | "version": "1.0.0",
362 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
363 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
364 | },
365 | "parse-json": {
366 | "version": "4.0.0",
367 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
368 | "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
369 | "requires": {
370 | "error-ex": "^1.3.1",
371 | "json-parse-better-errors": "^1.0.1"
372 | }
373 | },
374 | "path-exists": {
375 | "version": "3.0.0",
376 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
377 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
378 | },
379 | "pify": {
380 | "version": "3.0.0",
381 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
382 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
383 | },
384 | "pkg-conf": {
385 | "version": "2.1.0",
386 | "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz",
387 | "integrity": "sha1-ISZRTKbyq/69FoWW3xi6V4Z/AFg=",
388 | "requires": {
389 | "find-up": "^2.0.0",
390 | "load-json-file": "^4.0.0"
391 | }
392 | },
393 | "signale": {
394 | "version": "1.4.0",
395 | "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz",
396 | "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==",
397 | "requires": {
398 | "chalk": "^2.3.2",
399 | "figures": "^2.0.0",
400 | "pkg-conf": "^2.1.0"
401 | }
402 | },
403 | "strip-bom": {
404 | "version": "3.0.0",
405 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
406 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM="
407 | },
408 | "supports-color": {
409 | "version": "5.5.0",
410 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
411 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
412 | "requires": {
413 | "has-flag": "^3.0.0"
414 | }
415 | }
416 | }
417 | }
418 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-test-framework",
3 | "version": "1.0.0",
4 | "description": "Estudo de funcionamento interno de mock do jest",
5 | "private": true,
6 | "author": "Paulo Gonçalves Gonçalves ",
7 | "license": "MIT",
8 | "scripts": {
9 | "test": "node index.js ./**/*.test.js"
10 | },
11 | "dependencies": {
12 | "chalk": "2.4.2",
13 | "signale": "1.4.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/thumb-war.js:
--------------------------------------------------------------------------------
1 | const utils = require('./utils')
2 |
3 | function thumbWar(player1, player2) {
4 | const numberToWin = 2
5 | let player1Wins = 0
6 | let player2Wins = 0
7 | while (player1Wins < numberToWin && player2Wins < numberToWin) {
8 | const winner = utils.getWinner(player1, player2)
9 | if (winner === player1) {
10 | player1Wins++
11 | } else if (winner === player2) {
12 | player2Wins++
13 | }
14 | }
15 | return player1Wins > player2Wins ? player1 : player2
16 | }
17 |
18 | module.exports = thumbWar
19 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | function getWinner(player1, player2) {
2 | const winningNumber = Math.random()
3 | return winningNumber < 1 / 3
4 | ? player1
5 | : winningNumber < 2 / 3
6 | ? player2
7 | : null
8 | }
9 |
10 | module.exports = {getWinner}
11 |
--------------------------------------------------------------------------------
/tests/__mocks__/utils.js:
--------------------------------------------------------------------------------
1 | function fn(impl = () => {}) {
2 | const mockFn = (...args) => {
3 | mockFn.mock.calls.push(args)
4 | return impl(...args)
5 | }
6 | mockFn.mock = {calls: []}
7 | return mockFn
8 | }
9 |
10 | module.exports = {
11 | getWinner: fn((p1, p2) => p2)
12 | }
13 |
--------------------------------------------------------------------------------
/tests/external-mock-module.test.js:
--------------------------------------------------------------------------------
1 | require('./__mocks__/utils') // prime the cache
2 | const utilsPath = require.resolve('../src/utils')
3 | const mockUtilsPath = require.resolve('./__mocks__/utils')
4 | require.cache[utilsPath] = require.cache[mockUtilsPath]
5 |
6 | const thumbWar = require('../src/thumb-war')
7 | const utils = require('../src/utils')
8 |
9 | test('Teste de mock utilizando arquivo em __mocks__', async () => {
10 | const winner = thumbWar('Paulo Gonçalves', 'Fulano')
11 | expect(winner).toBe('Fulano')
12 | expect(utils.getWinner.mock.calls).toBeDeepStrictEqual([
13 | ['Paulo Gonçalves', 'Fulano'],
14 | ['Paulo Gonçalves', 'Fulano']
15 | ])
16 | })
17 |
--------------------------------------------------------------------------------
/tests/spy.test.js:
--------------------------------------------------------------------------------
1 | const { spyOn } = require('../index')
2 |
3 | const thumbWar = require('../src/thumb-war')
4 | const utils = require('../src/utils')
5 |
6 | test('Teste de spy', async () => {
7 | spyOn(utils, 'getWinner')
8 | utils.getWinner.mockImplementation((p1, p2) => p1)
9 |
10 | const winner = thumbWar('Paulo Gonçalves', 'Fulano')
11 | expect(winner).toBe('Jogador não existente')
12 | expect(utils.getWinner.mock.calls).toBeDeepStrictEqual([
13 | ['Paulo Gonçalves', 'Fulano'],
14 | ['Paulo Gonçalves', 'Fulano']
15 | ])
16 |
17 | // cleanup
18 | utils.getWinner.mockRestore()
19 | })
20 |
--------------------------------------------------------------------------------