Boilerplate Testes de API em TypeScript
Pré-requisitos
- Instalar o Node
Ambiente
Para executar os testes localmente, estou utilizando o ServeRest
Link do Repo: https://github.com/ServeRest/ServeRest
ServeRest está disponível de forma online, no npm e no docker.
Instalando Dependências
- Rodar o comando
npm i
- Criar arquivo
.env
na raiz do projeto
Criar o arquivo com as seguintes variáveis
PROD=https://serverest.dev
DEV=http://localhost:3000
- Rodar os testes localhost
npm run test-dev
- Para rodar os testes em Produção
npm run test-prod
Configuração do Projeto
Estrutura de Pastas
O projeto esta dividido da seguinte maneira:
[api-tests-typescript]
[src] -> código fonte
[config] -> arquivos de configuração ambiente
[factory] -> métodos para criar objetos
[services] -> funções que retornam requisições das rotas
[test] -> Arquivos de testes com Mocha e Chai.
.env -> arquivo com variáveis de ambiente(normalmente não commitada)
.mocharc.js -> arquivo de configuração do Mochawesome
Services
Services são funções que retornam requests pré-estabelecidas de cara um dos endpoints, sendo responsável apenas por devolver o conteúdo produzido pela request. Essas funções podem ter parâmetros ou não.
Exemplo:
export async function postLogin(credentials: any) {
return await chai
.request(conf.url)
.post('/login')
.set('Content-Type', 'application/json')
.send({
email: credentials.email,
password: credentials.password
})
Este trecho de código, exibe a função de Login (postLogin
), na qual apresenta um parâmetro credentials
.
Foi utilizado o chai-http
para criar a estrutura do request, para saber mais sobre seu uso acesse: https://www.chaijs.com/plugins/chai-http/
Factory
Factory, é um padrão criacional onde se utiliza funções ou métodos para gerar objetos de forma independente, sem o uso de classes concretas
Exemplo:
const faker = require('faker');
const UserFactory = {
createUser(){
let firstName: string = faker.name.firstName();
let lastName: string = faker.name.lastName();
let nome = `${firstName} ${lastName}`
let email = `${firstName.toLocaleLowerCase()}.${lastName.toLocaleLowerCase()}@email.com`
let password = faker.internet.password();
let administrador = 'true'
return {
"nome": nome,
"email": email,
"password": password,
"administrador": administrador
}
}
}
export default UserFactory;
Neste expelo, a função createUser()
retorna um objeto que não utiliza uma classe concreta, e para utiliza-la basta importar para as classes de teste.
//...
before(async () => {
user = UserFactory.createUser();
await postUser(user);
token = await returnToken(user);
})
//...
Schema
Para realizar os testes de contrato, usei a lib Joi, seu uso é muito simples e basicamente criamos uma estrutura para validar se o retorno de uma requisição segue exatamente os modelo criado pelo Joi.
Exemplo da linguagem
import Joi = require('joi');
const loginSchema = Joi.object({
message: Joi.string().required(),
authorization: [Joi.string(),Joi.number()]
})
module.exports = { loginSchema };
Dentro dos testes basta importar o Joi e criar uma validação usando o Joi.assert()
const schema = require('../schema/Login-schema');
//any code
it('Login Success', async ()=>{
response = await postLogin(user);
expect(response.statusCode).to.eq(200);
expect(response.body.message).to.eq('Login realizado com sucesso');
Joi.assert(response.body, schema.loginSchema);
})