├── .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 | --------------------------------------------------------------------------------