No artigo anterior vimos um exemplo de como podemos usar o MSW para interceptar uma requisição HTTP e retornar informações fictícias para usar em testes unitários. Quando fazemos isso é importante termos em mente que a requisição real não é executada, pois ela é interceptada pelo msw
.
Neste artigo, vamos ver um exemplo de como deixar as funções do msw
em um escopo maior para que os testes - it
- levem em conta o mock
. Assim, evitamos de a cada teste - it
- inserir o código novamente, isto é, o DRY
- Don't Repeat Yourself.
Show me the code
Imaginem o seguinte cenário: precisamos criar 2 testes para verificarmos se os dados que estão vindo da API estão corretos e o que fazemos com estes dados estão de acordo com a regra de negócio que definimos. Então, concluímos que a resposta da API deve ser sempre de sucesso, ou seja, HTTP Status Code 2xx - 200, 201, 204...
// getUserInfoGithub.js
import axios from 'axios';
export const getUserInfoGithub = async ({ username }) => {
const { data } = await axios.get(
`https://api.github.com/users/${username}`
);
return {
...data,
hasTwitter: Boolean(data.twitter_username),
hasBlog: Boolean(data.blog),
};
};
const { setupServer } = require('msw/node');
const { rest } = require('msw');
const getUserInfoGithub = require('./getUserInfoGithub');
const endpoint = "https://api.github.com/users/:username";
const createServer = () =>
setupServer(
rest.get(endpoint, (request, response, ctx) =>
response(
ctx.status(200),
ctx.json({
id: 12345678,
twitter_username: '@TwitterUser',
blog: 'https://gist.github.com/username',
})
)
)
);
beforeAll(() => createServer.listen());
afterEach(() => createServer.resetHandlers());
afterAll(() => createServer.close());
describe('Testing User Service', () => {
it('should return user info twitter username', async () => {
const response = await getUserInfoGithub('MockUser');
expect(response.hasTwitter).toBeTruthy();
});
it('should return user info link blog', async () => {
const response = await getUserInfoGithub('MockUser');
expect(response.hasBlog).toBeTruthy();
});
});
Sobre o código acima, vamos as explicações:
A diferença desse código para o código do artigo anterior é o use do beforeAll
do Jest. Traduzindo, o beforeAll
vai executar o código dentro dele antes de todos os testes rodarem. E o código que será executado é a função createServer
.
Então, antes do primeiro it
executar, o servidor mock será executado e ficará ouvindo - listen
- as requisições que serão feitas realmente.
O afterEach
significa que depois de cada teste - it
- o msw
vai limpar ou resetar os manipuladores de requisição para que não afete outros testes unitários do projeto.
E o afterAll
determina o que vai acontecer depois que todos os testes forem executados, nesse caso irá limpar todas os mocks
que foram abertos e fechar a conexão com o servidor fictício.
Pontos de Atenção
Ao fazermos isso, todos os testes de dentro desse arquivo que na realidade farão uma requisição GET
para esse endpoint vão obedecer esse mock. Isso é importante saber, porquê se em algum momento você precisar testar uma resposta HTTP Status Code diferente de 2XX, não vai dar certo. Nesse caso você precisará criar o escopo de outra forma. Segue abaixo as diferenças:
Note que deixamos a variável createServer
flexível para ser usada em outros lugares e invocar outros métodos do setupServer
. Assim, podemos criar outro teste para testarmos uma resposta diferente de 200
- OK.
it('should return user info link blog', async () => {
createServer.use(
rest.get(endpoint, (request, response, ctx) =>
response(ctx.status(400))
)
);
await expect(getUserInfoGithub('MockUser')).rejects.toThrow();
});
Nesse cenário usamos a função use
do setupServer
onde conseguimos encadear outro mock, agora com uma resposta diferente, o HTTP Status Code 400
- BAD REQUEST.
E assim conseguimos testar o erro usando o await
antes do expect
, por se tratar de uma Promise
no retorno da função. E o expect
estende o método rejects
- que lembra o then
- para recuperar o retorno.
Diante disso temos os resultados:
Outro ponto de atenção é que esse código que fizemos vai funcionar dentro do escopo desse arquivo de teste unitário. Mas você pode como que escalar ainda mais o escopo dele. Geralmente no projeto, tem um arquivo chamado jest.setup.js
ou setupTests.js
.
Dentro dele, você pode criar um servidor mock e colocar as requisições que você deseja interceptar para todos os arquivos de testes, como abaixo:
const { setupServer } = require('msw/node');
const { rest } = require('msw');
const createServer =
setupServer(
rest.get(endpoint, (req, res, ctx) => ()),
rest.post(endpoint, (req, res, ctx) => ()),
rest.put(endpoint, (req, res, ctx) => ()),
rest.delete(endpoint, (req, res, ctx) => ()),
);
beforeAll(() => createServer.listen())
afterEach(() => createServer.resetHandlers())
afterAll(() => createServer.close())
E depois aplicar essa configuração no arquivo jest.config.js
:
// jest.config.js
module.exports = {
setupFilesAfterEnv: ['./jest.setup.js'],
}
Top comments (0)