Logo

Publicado

- 4 min read

Crie uma API com Node.js e TypeScript usando o padrão TDD

img of Crie uma API com Node.js e TypeScript usando o padrão TDD

Introdução

Neste post, vamos explorar como criar uma API utilizando Node.js e TypeScript aplicando o padrão de desenvolvimento TDD (Test-Driven Development). O TDD é uma metodologia que prioriza a escrita de testes antes de implementar a lógica da aplicação, resultando em código mais bem estruturado e com menos bugs. Ao final deste tutorial, você terá uma API funcional e testada, pronta para ser utilizada em qualquer aplicação.

Pré-requisitos

Antes de começarmos, certifique-se de ter o seguinte instalado no seu ambiente de desenvolvimento:

  • Node.js (versão 14 ou superior)
  • npm (gerenciador de pacotes do Node.js)
  • TypeScript
  • Um editor de código (como Visual Studio Code)

Conceitos principais

1. O que é TDD?

O TDD é uma abordagem de desenvolvimento que se concentra em escrever testes antes de escrever o código funcional que implementa aqueles testes. O ciclo TDD é simples:

  1. Escreva um teste que falha.
  2. Escreva código suficiente para passar no teste.
  3. Refatore o código, mantendo os testes passando.

2. Instalação de dependências

Para iniciar nosso projeto, crie uma nova pasta e dentro dela, execute os seguintes comandos:

   npm init -y
npm install express @types/express typescript ts-node nodemon --save
npm install jest ts-jest @types/jest --save-dev

Em seguida, crie um arquivo de configuração do TypeScript (tsconfig.json):

   {
	"compilerOptions": {
		"target": "ES2020",
		"module": "commonjs",
		"strict": true,
		"esModuleInterop": true
	}
}

E um arquivo de configuração do Jest (jest.config.js):

   module.exports = {
	preset: 'ts-jest',
	testEnvironment: 'node'
}

Mini-projeto prático: Criando uma API simples

1. Estrutura de Pastas

Crie a seguinte estrutura de pastas para o seu projeto:

   /src
  /controllers
  /routes
  /tests
  index.ts

2. Implementando a API

Vamos criar uma API simples que gerencia um recurso de “tarefas”.

a) Criando o modelo de Tarefa

Dentro da pasta /src crie um arquivo task.ts:

   export interface Task {
	id: number
	title: string
	completed: boolean
}

const tasks: Task[] = []

export const getTasks = () => tasks

export const createTask = (title: string): Task => {
	const newTask: Task = {
		id: tasks.length + 1,
		title,
		completed: false
	}
	tasks.push(newTask)
	return newTask
}

b) Criando o controller

Em /src/controllers, crie taskController.ts:

   import { Request, Response } from 'express'
import { createTask, getTasks } from '../task'

export const getAllTasks = (req: Request, res: Response) => {
	const tasks = getTasks()
	res.json(tasks)
}

export const addTask = (req: Request, res: Response) => {
	const { title } = req.body
	const task = createTask(title)
	res.status(201).json(task)
}

c) Criando as rotas

Em /src/routes, crie taskRoutes.ts:

   import { Router } from 'express'
import { getAllTasks, addTask } from '../controllers/taskController'

const router = Router()

router.get('/tasks', getAllTasks)
router.post('/tasks', addTask)

export default router

d) Configurando o servidor

No arquivo index.ts, configure o servidor Express:

   import express from 'express'
import taskRoutes from './routes/taskRoutes'

const app = express()
const PORT = process.env.PORT || 3000

app.use(express.json())
app.use('/api', taskRoutes)

app.listen(PORT, () => {
	console.log(`Server running on http://localhost:${PORT}`)
})

Testes

1. Escrevendo os testes

Dentro da pasta /tests, crie taskController.test.ts:

   import request from 'supertest'
import app from '../index' // Exporte o app do arquivo index.ts

describe('Task API', () => {
	it('should create a new task', async () => {
		const response = await request(app).post('/api/tasks').send({ title: 'New Task' })
		expect(response.status).toBe(201)
		expect(response.body.title).toBe('New Task')
	})

	it('should return all tasks', async () => {
		const response = await request(app).get('/api/tasks')
		expect(response.status).toBe(200)
		expect(Array.isArray(response.body)).toBeTruthy()
	})
})

2. Executando os testes

Adicione o seguinte comando ao package.json para executar os testes:

   "scripts": {
  "test": "jest"
}

Para rodar os testes, execute:

   npm test

Padrões de projeto aconselháveis

  1. Separação de preocupações: Use o padrão MVC (Model-View-Controller) para organizar o código.
  2. Injeção de dependências: Facilita o teste e a manutenção.
  3. Boas práticas de nomenclatura: Torne seu código legível e compreensível.

Prós e Contras do TDD

Prós

  • Código bem testado: Produz uma base de código mais robusta e livre de bugs.
  • Refatoração mais segura: Permite melhorias na base de código sem perder a funcionalidade.

Contras

  • Curva de aprendizado: Para iniciantes, pode ser desafiador entender a mentalidade de TDD.
  • Tempo adicional: O desenvolvimento pode inicialmente ser mais lento devido à necessidade de escrever testes.

Performance de cada ferramenta

  • Node.js: Alta performance para aplicações de I/O intensivo, ideal para APIs.
  • TypeScript: Adiciona tipos ao JavaScript, resultando em uma melhor manutenção e menos erros comuns.
  • Jest: Alta performance em testes, com paralelismo e capacidade de mocks.

Dicas para próximos passos

  • Explore o uso de middlewares no Express.
  • Aprenda sobre autenticação e autorização em APIs.
  • Experimente adicionar um banco de dados ao seu projeto, como MongoDB ou PostgreSQL.

Possíveis erros e soluções

  1. Erro: “Cannot find module”: Certifique-se de que todas as dependências estão instaladas adequadamente.
  2. Erro de rota 404: Verifique se as rotas estão definidas corretamente e se o servidor está em execução.

Com este guia, você agora possui uma base sólida em como criar uma API utilizando Node.js e TypeScript com TDD. Continue praticando e explorando novas funcionalidades!