MSW - Mock Service Worker - Introdução e Teste Unitário
Tags: testing, node, javascript, react
Published: 2022-09-15 12:43:59

### Onde usar o MSW?

Essa biblioteca pode ser usada em pelo menos três circunstâncias: **testes**, **desenvolvimento** e **_debugging_**. Mas independente da circunstância o objetivo do MSW é interceptar requisições que são feitas pela aplicação para alguma determinada API.

Este artigo se concentrará especificamente nos **Testes**. Nos próximos artigos vou trazer como configurar o MSW para criar uma API Fake ao desenvolvermos uma aplicação em React.

### Testes

Com o MSW nós podemos criar um mock, isto é, simular um comportamento de uma classe ou objeto **real** com dados **não-reais** ou fictícios, por exemplo, em testes unitários. 

Neste artigo, o foco é apenas em um teste unitário com NodeJS + Jest. No próximo artigo vou mostrar como reutilizar o _mock_ em vários testes ao mesmo tempo.

---

### Exemplo em NodeJS com Jest

```js
// getUserInfoGithub.js
import axios from 'axios';

export const getUserInfoGithub = async ({ username }) => {
  // Desestruturando o `data` do retorno da chamada
  const { data } = await axios.get(
     `https://api.github.com/users/${username}`
  );

  return data;
};
```

```js
// getUserInfoGithub.spec.js

import { setupServer } from 'msw/node';
import { rest } from 'msw';

import getUserInfoGithub from './getUserInfoGithub';

const endpoint = 'https://api.github.com/user/:username';
const httpStatusCode = 200;

it("should return user info of the github api", async () => {
  // Criando mock de interceptação da requisição
  setupServer(
    rest.get(endpoint, (request, response, ctx) => {
      const { username } = request.params;

      return response(
        ctx.status(httpStatusCode),
        ctx.json({
           id: 123456789,
           login: username,
           name: "John Doe",
           location: "Brasil",
        });
      );
    })
  ).listen();

  const response = await getUserInfoGithub('MOCK');
  const expected = {
     id: 123456789,
     name: "John Doe",
     location: "Brasil",
  };

  expect(response).toMatchObject(expected);
});
```

Sobre o código acima, vamos as explicações:

Invocamos a função `setupServer` que é responsável por criar um `listener`, ou seja, um evento que tem como objetivo **ouvir** um comportamento real. Nesse caso, o comportamento é uma requisição GET para a API do Github. É por isso que ao final da função, invocamos a função `listen()` - não esqueçam de colocá-la.

Dentro da função é declarado um `rest.get` que será disparada no momento que na função `getUserInfoGithub` for feita uma requisição GET. Nesse caso estou utilizando o `axios`, mas pode ser qualquer biblioteca para fazer requisições HTTP.

Dentro da função `rest.get` temos três variáveis importantes que descrevem a **requisição**. No entanto, não queremos apenas simular a requisição, mas também a **resposta** da requisição. Pensando nisso, leia as observações abaixo:

1. O primeiro parâmetro da função `rest.get` recebe um `endpoint`. Coloque nesse parâmetro, o endpoint em que a requisição será feita de verdade.

2. O segundo parâmetro da função `rest.get` recebe uma `callback function` que retorna três objetos: `request`, `response` e `ctx`. E dentro dessa função de `callback` retorna uma função chamada `response`, que recebe dois parâmetros:

`ctx.status(httpStatusCode)` - aqui é onde passamos qual será o código de status que será simulado ou retornado da API _fake_, podendo ser qualquer um deles: 200, 201, 400, 401, 404, 500. O `ctx` é o `context`. Com essa função estamos determinando o **cenário** ou **contexto** que queremos apresentar ao teste.

`ctx.json(mockResponse)` - aqui é onde passamos quais serão os dados de retorno da API _fake_ no formato JSON. Nesse caso utilizei apenas um objeto com apenas algumas propriedades que retorna da requisição real feita para o endereço `https://api.github.com/users/deesouza`. 

### Observações

Você pode usar a função `rest` do pacote `msw` para interceptar qualquer requisição de qualquer verbo do protocolo HTTP: `[GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD]`

---

Tendo esses pontos em mente, agora é testar a requisição e o retorno com o `expect` e teremos o resultado:

![Imagem que mostra o teste já executado com sucesso usando JEST com 100% de cobertura](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nm6g0nyhf5scso1ycd5o.png)

Espero que esse artigo o ajude de alguma maneira.

---

## Referências

[MSW JS](https://mswjs.io/docs/)