Olá, sou Raphael Girão, instrutor da Alura. Dou-lhe as boas-vindas ao nosso curso de testes com o Node.js.
Audiodescrição: Raphael Girão se identifica como uma pessoa morena de cabelos pretos e olhos castanhos. Está com uma camiseta preta, sentado em uma cadeira gamer preta. Ao fundo, estante branca com decorações e iluminação azul.
Neste curso, você vai aprender sobre padrões de testes e boas práticas na criação deles, assim como a criar:
Além disso, será abordado o desenvolvimento orientado a testes utilizando TDD (Test Driven Development).
Todos esses conceitos serão aplicados em nossa API de livraria, onde podemos cadastrar livros, autores e pessoas usuárias. As pessoas usuárias podem se autenticar e, quando autenticadas, podem também alugar livros.
Se você não está acompanhando a formação de autenticação, testes e segurança em Node.js, será necessário possuir alguns pré-requisitos, como:
Além de nossos vídeos, oferecemos exercícios, um fórum de discussão e uma comunidade no Discord da Alura para solucionar suas dúvidas.
Então, vamos codar?
Olá, pessoal. Vamos dar início ao curso de testes com o Node.js. Para este curso, vamos utilizar uma API de uma livraria.
Dentro dessa API temos algumas funcionalidades novas. Entre elas, está a parte de usuário, onde podemos fazer o cadastramento de pessoas usuárias e elas podem se autenticar.
Quando essas pessoas usuárias estão autenticadas, elas podem alugar livros, cadastrar novos livros e pessoas autoras. Vamos dar uma olhada no projeto?
Ao abrir o menu lateral do VS Code (atalho "Ctrl + Shift + E"), conseguimos conferir as pastas e a estrutura do nosso projeto, ou seja, a arquitetura.
Dentro de "src" (lê-se source), temos as pastas de:
Dentro dessa pasta de testes, já temos duas pastas que vieram do curso anterior, chamadas "models" e "routes".
Portanto, vamos continuar a seguir esse padrão, para que quem venha a utilizar o projeto possa entender todos os testes criados. Esse padrão se baseia pela pasta "src".
Como queremos criar um novo teste, vamos escolher uma dessas pastas para testar. Nesse caso, vamos escolher a pasta de "services" e conferir quais os arquivos temos dentro dela. Entre eles, temos authService.js
, autoresService.js
, editorasService.js
. Vamos precisar escolher um deles.
Vamos escolher authService.js
, que é a parte nova no nosso projeto, onde temos o módulo de cadastro e login de pessoas usuárias. Esse arquivo será escolhido porque é um módulo novo e ainda não possui testes.
Nele, temos duas funções, a de login()
e cadastrarUsuario()
. Para criar nossos primeiros testes, vamos escolher a parte de cadastro de pessoas usuárias. Isso nos permitirá definir um novo padrão de testes, que facilitará o entendimento de pessoas novas no projeto.
authService.js
:
class AuthService {
async login(data) {
// código omitido…
}
async cadastrarUsuario (data) {
data.senha = await bcryptjs.hash (data.senha, 8);
const usuario = new Usuario (data);
try {
const resposta = await usuario.salvar (usuario);
return { message: 'usuario criado', content: resposta };
} catch (err) {
throw new Error(err.message);
}
}
}
Agora, vamos fechar o arquivo authService.js
e abrir a pasta de testes. Dentro dela, vamos criar uma nova pasta chamada "services", baseada na arquitetura do source.
Em "tests > services", vamos criar um novo arquivo que será referente ao arquivo de service para o qual vamos criar os testes. No nosso caso, é o authService
. Portanto, o nome do arquivo será authService.test.js
, informando que é um arquivo de teste.
Agora que criamos o arquivo, precisamos definir o que vamos testar, quais são as regras que vamos validar na função de cadastrarUsuario()
.
Para isso, trouxe um documento onde temos todas as regras que vamos precisar testar. Vamos abrir o bloco de notas e copiar as regras que vamos utilizar.
- O usuário deve possuir um nome, email e senha
- A senha do usuário precisa ser criptografada quando for salva no banco de dados
- Não pode ser cadastrado um usuário com e-mail duplicado
- Ao cadastrar um usuário, deve ser retornado mensagem informando que o usuário foi cadastrado
- Ao cadastrar um usuário, validar retorno do usuário
Então, vamos copiar e levar essas regras para o projeto. Vamos selecionar tudo ("Ctrl + A"), copiar ("Ctrl + C") e minimizar o bloco de notas. Agora, na pasta de "test > services" no VS Code, vamos criar um novo arquivo chamado testes-authService.txt
. Nele, vamos colar ("Ctrl + V") as regras dos testes.
Já que temos nossas regras definidas, vamos selecionar e copiar a primeira regra para levá-la aos nossos testes. Em authService.test.js
, vamos criar nosso primeiro cenário de teste.
Começaremos importando o describe
para poder unificar todos os testes da função de cadastrarUsuario()
. Na primeira linha, faremos um import
e chamaremos a função describe
entre chaves.
Depois de importá-la de @jest/globals
, vamos unificar colocando um bloco de describe
na próxima linha.
Primeiro, descrevemos o que queremos. Por exemplo, a string Testando a authService.cadastrarUsuario
, que é o nome da função a ser testada.
Ele já fez a chamada da função e, dentro dela, vamos criar nosso primeiro cenário de teste. Em uma nova linha, vamos dar um it()
e colar a mensagem O usuário deve possuir um nome, email e senha
que é a regra do primeiro teste.
Depois disso, vamos acrescentar uma vírgula e chamar o escopo do teste. Para padronizar o teste, vamos criar uma estrutura de Mock (simulação), que será o dado que vamos passar para testar.
Dentro da arrow function, vamos criar uma constante chamada usuarioMock
que será igual à abre e fecha chaves. Como é um teste em que queremos validar se a service está recebendo as informações adequadamente, é um teste de erro.
Portanto, não vamos passar todas as informações do usuário. Deixaremos faltando alguns campos. Então, vamos passar um nome
como Raphael
e um email
que será rafael@teste.com.br
. Como queremos validar um erro, não vamos passar uma senha.
authService.test.js
:
import { describe } from '@jest/globals';
describe('Testando a authService.cadastrarUsuario', () => {
it('O usuario deve possuir um nome, email e senha', () => {
const usuarioMock = {
nome: 'Raphael',
email: 'raphael@teste.com.br'
};
});
});
Feito isso, vamos chamar a service para testar a função de cadastro. No começo do arquivo, vamos importar AuthService
a partir do local correto do diretório. Voltando dois diretórios, temos a nossa base. Vamos chamar service
e, em seguida, a authService
.
Após importá-la, criaremos uma instância const authService = new AuthService()
. Com isso, conseguimos acessar a função de cadastrarUsuario()
.
Em it()
, vamos criar a segunda etapa do teste. Faremos const usuarioSalvo
igual à authService.cadastrarUsuario()
, passando os dados de usuarioMock
.
Por fim, vamos para a última etapa do teste, que é fazer a comparação entre o Mock e o envio para a service. Para isso, vamos usar o expect()
.
Em uma nova linha, faremos await expect()
, passando o usuarioSalvo
. Já que queremos testar um retorno de erro, precisamos de uma função chamada rejects
, que vai validar qualquer mensagem de erro. Em seguida, chamaremos a função .toThrowError()
, que recebe uma mensagem que ainda vamos verificar.
Como usamos um await
, devemos passar a função como assíncrona. Por isso, escrevemos async
antes de () => {}
.
import AuthService from '../../services/authService';
const authService = new AuthService();
describe('Testando a authService.cadastrarUsuario', () => {
it('O usuario deve possuir um nome, email e senha', async () => {
const usuarioMock = {
nome: 'Raphael',
email: 'raphael@teste.com.br'
};
const usuarioSalvo = authService.cadastrarUsuario(usuarioMock);
await expect(usuarioSalvo).rejects.toThrowError('');
});
});
Vamos agora na authService
para validar e verificar qual é essa mensagem. Se observarmos, a service não possui nenhuma validação para os campos obrigatórios. Portanto, identificamos uma melhoria para o código. Agora, precisaremos refatorá-lo para que atenda a esse requisito dessa regra de negócio.
Portanto, vamos no início de cadastrarUsuario()
para adicionar uma validação com if
.
Se não houver o data.senha
, queremos que retorne uma mensagem de erro, uma exceção. Então, vamos dar um Throw new Error()
, passando qual será a mensagem de exceção que esperamos receber. Nesse caso, vamos passar a string A senha de usuário é obrigatória!
.
Agora, vamos copiar essa mensagem, porque como vamos fazer um teste, essa mensagem tem que ser exatamente igual.
Também vamos aproveitar para fazer uma melhoria. Vamos selecionar o trecho de código do ìf
ao const usuario
e colocá-lo dentro do Try-Catch. Assim, vai estar resguardado pela validação. Ele vai tentar, caso dê algum erro, já cai no catch
.
authService.js
:
class AuthService {
// código omitido…
async cadastrarUsuario (data) {
try {
if (!data.senha) {
throw new Error('A senha de usuário é obrigatória!');
}
data.senha = await bcryptjs.hash (data.senha, 8);
const usuario = new Usuario (data);
const resposta = await usuario.salvar (usuario);
return { message: 'usuario criado', content: resposta };
} catch (err) {
throw new Error(err.message);
}
}
}
Com isso, voltamos para o authService.test.js
para colar a mensagem no toThrowError()
.
await expect(usuarioSalvo).rejects.toThrowError('A senha de usuário é obrigatória!');
Agora que temos a validação, o teste está finalizado. Como vamos rodar esse teste? Vamos precisar executá-lo.
Então, vamos abrir o package.json
e conferir os comandos que já temos nesse projeto. Dentro de scripts
, já tem alguns comandos que utilizamos anteriormente. Vamos verificar qual será o novo comando.
Para isso, já preparamos esse comando. Após esse test:coverage
, vamos acrescentar uma vírgula e adicionar o novo cenário de teste test:auth:service
:
package.json
:
"scripts": {
"dev": "nodemon server.js",
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
"test:watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watchAll",
"test:coverage": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watchAll --coverage",
"test:auth:service": "node --experimental-vm-modules node_modules/jest/bin/jest.js --testPathPattern=src/test/services/authService.test.js"
},
Esse novo cenário de teste está executando da mesma forma que os anteriores e está passando o path (caminho) do arquivo. Assim, vamos executar apenas o teste que acabamos de criar.
Agora, vamos abrir o terminal integrado com "Ctrl + `" para executar esse novo comando. Primeiro, vamos dar um npm run test:auth:service
e esperar para conferir o que vai retornado do teste.
npm run test:auth:service
PASS src/test/services/authService.test.js
Testanto a authService.cadastrarUsuario
O usuário deve possuir um nome, email e senha (15 ms)
- Test Suites: 1 passed, 1 total
- Tests: 1 passed, 1 total
- Snapshots: 0 total
- Time: 1.817 s, estimated 4 s
O teste funcionou perfeitamente. Podemos fechar o terminal.
Vamos conferir estrutura que utilizamos e o padrão que criamos no teste. Em authService.test,js
, conseguimos notar algumas características.
Primeiro, vamos apertar "Ctrl + Shift + P" para executar o EsLint para indentar e corrigir problemas no teste.
Conseguimos perceber que temos três etapas. A primeira é chamada de Arrange, porque é onde vamos dizer quais são as informações que queremos validar.
A segunda etapa é chamada de Act, onde vamos buscar as informações na função, no service, ou em qualquer outra função que você deseja testar.
Por último, temos uma etapa que se chama de Assert, onde vamos comparar o Arrange com o Assert.
Colocamos comentários para delimitar cada etapa.
authService.test.js
import AuthService from '../../services/authService';
const authService = new AuthService();
describe('Testando a authService.cadastrarUsuario', () => {
// arrange
it('O usuario deve possuir um nome, email e senha', async () => {
const usuarioMock = {
nome: 'Raphael',
email: 'raphael@teste.com.br'
};
// act
const usuarioSalvo = authService.cadastrarUsuario(usuarioMock);
// assert
await expect(usuarioSalvo).rejects.toThrowError('A senha de usuário é obrigatória!');
});
});
Assim, acabamos de criar um padrão conhecido como padrão Triple A. Desse modo, criamos um teste muito mais fácil de ser entendido e qualquer nova pessoa que for verificar o teste, vai entendê-lo com mais facilidade.
Agora que conhecemos o padrão Triple A, podemos desenvolver novos testes seguindo esse padrão para facilitar o desenvolvimento de testes.
No próximo vídeo, vamos aprender como classificar testes e como esses testes são analisados por outras pessoas desenvolvedoras. Até o próximo vídeo.
Vamos continuar com o curso de testes com Node.js. No último vídeo, realizamos a criação do nosso primeiro teste.
Esse primeiro teste seguiu um padrão específico conhecido como padrão Triple A, que consiste em três etapas. No projeto no VS Code, vamos analisar o teste em authService.test.js
. Nele, fizemos as separações do Arrange, Act e Assert.
Mas, como esse teste é classificado? Quais são as características que podemos atribuir a esse teste?
Analisando o teste, percebemos que ele está verificando uma funcionalidade, uma função. Por isso, ele é conhecido como um teste unitário, pois vai testar uma pequena parte do código. Nesse caso, é a função de cadastrarUsuario()
.
No entanto, ele possui outras classificações e características. Quais são elas?
O teste tem acesso diretamente ao código, ao service. Assim, vamos abrir o arquivo authService.js
. Dentro dele, notamos que o teste unitário está sendo validado diretamente no código e obtivemos acesso para fazer uma melhoria.
Portanto, como podemos classificar esse teste? Ele pode ser classificado como um teste de caixa-branca.
Se levarmos em consideração os termos "caixa-preta" ou "caixa-branca", lembramos do aparelho dos aviões que guardam algumas informações do voo. Nesse caso, como é uma caixa-branca, temos acesso direto a essas informações do código.
Qual é a importância de ter acesso direto ao código? Temos a possibilidade de melhoria do código, uma vez que ao ter acesso ao código, conseguimos refatorar e melhorar sua qualidade.
Essa são algumas das classificações para testes. No próximo vídeo, vamos conhecer um pouco mais sobre outras classificações de testes.
O curso Node.js: implementando testes em uma API Rest possui 82 minutos de vídeos, em um total de 41 atividades. Gostou? Conheça nossos outros cursos de Node.JS em Programação, ou leia nossos artigos de Programação.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.