> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/contributor/contributor-pt/guias-para-colaboradores/testing-standards/testing-services-deprecated.md).

# Testar Services (obsoleto)

{% hint style="warning" %}
Esta é uma abordagem obsoleta para testar serviços. Para novos serviços, consulte [Serviços de teste (Well-Known-Component)](/contributor/contributor-pt/guias-para-colaboradores/testing-standards/testing-services-wkc.md).
{% endhint %}

Os serviços DEVEM ser testados principalmente usando **testes de API**, ou seja, um conjunto de testes que exercitam o código do serviço através da sua API, colocando o serviço em funcionamento, com as suas dependências externas simuladas (bases de dados e APIs). **Teste unitário** DEVEM ser incluídos nos casos em que sejam encontradas secções utilitárias de código com um elevado número de casos a exercer ou código não performante, tornando impossível ou difícil testá-lo com testes de API. A justificação para isto é que, devido à nossa arquitetura de microserviços, que reduz as responsabilidades e, consequentemente, a quantidade de código a testar, a lógica dos serviços é simples, tornando os testes de API na opção com melhor relação tempo/valor ao garantir que os serviços funcionam corretamente.

## Pilha de testes

Os serviços DEVEM ser testados usando [Jest](https://jestjs.io/) como o principal framework de testes com [supertest](https://github.com/visionmedia/supertest) como o framework para configurar o servidor e testá-lo.

## Estrutura de diretórios

Como os serviços PODEM ter tanto testes de API como testes unitários, haverá mais do que um local para onde os testes irão:

* Os testes unitários DEVEM ficar junto do ficheiro ou módulo que estão a testar, com o mesmo nome, mas com a extensão `spec.ts` em vez de `ts`.
* Os testes de API irão exercitar código ao longo de todo o serviço, por isso DEVEM ser colocados num diretório `test` na raiz. Os ficheiros serão nomeados de acordo com o recurso do serviço que irão testar, ou seja, se os testes de API estiverem a testar o recurso `books`, normalmente em `/books`, o nome do ficheiro DEVE ser `books.spec.ts` e DEVE ser colocado no diretório `test` .

## O que testar

* Middlewares aplicados à rota (auth, etc.), para garantir que a rota funciona como esperado.
* A lógica dos controllers, para garantir que a rota faz o que esperamos que faça.

## Serviços de teste de API

Como mencionado anteriormente, os testes de API serão feitos usando Jest e supertest.

Para ilustrar como um developer fará testes de API, temos o seguinte exemplo:

```tsx
import express from "express"
import { authMiddleware } from "../auth"
import db from "../db"

const app = express()

app.get('/books', async (req, res) => {
	let books: Books[];
	if(req.query.author) {
		books = await db.getFilteredBooks({ author: req.query.author })
	} else {
		books = await db.getBooks()
	}
  res.json(books)
})

app.post('/books', authMiddleware, async (req, res) => {
	await db.insertBook(req.body)
	res.status(200).end()
})
```

Encontramos no exemplo uma rota com diferentes métodos HTTP, GET e POST. Ambos os endpoints referem-se ao mesmo recurso, books, por isso um ficheiro, chamado `books.spec.ts` DEVE ser criado no `test` diretório para conter os testes para eles.

Todas as rotas e os diferentes fluxos de execução DEVEM ser testados exaustivamente. Estes são os casos que o developer DEVE testar para estes endpoints:

* Pedir todos os livros funciona, respondendo com um 200 e a lista de todos os livros.
* Pedir todos os livros de um determinado autor funciona, respondendo com um 200 e a lista de todos os livros desse autor.
* Publicar um livro sem autenticação falha, respondendo com um 401 e uma mensagem de erro.
* Publicar um livro autenticado funciona, respondendo com um 200 e inserindo o livro.

Estes casos irão definitivamente ter os seus **it**s e a expectativa desses its DEVE conter pelo menos **o status de resposta esperado** e o que é **esperado no corpo da resposta** (se houver).

É assim que estes testes de endpoint devem ser escritos:

```tsx
import db from '../db'
import app from '../express_app.ts'
// Só simulamos dependências externas, como bases de dados
jest.mock('../db')

const mockDb = db as jest.Mocked<typeof db>

const server = supertest(app.getApp())

// Isto também pode ser escrito como /books?
describe('quando se pede o recurso books', () => {
	let url: string
	let aBook: Book
	let anotherBook: Book
	beforeEach(() => {
		url = '/books'
		aBook = { title: 'aTitle', author: 'anAuthor' }
		anotherBook = { title: 'anotherTitle', author: 'anotherAuthor' }
	})
	
	describe('quando se consulta os livros sem um autor', () => {
		beforeEach(() => {
			mockDb.getBooks.mockResolvedValueOnce([aBook, anotherBook])
		})

		it('deve responder com um 200 e todos os livros', () => {
			return server
	      .get(url)
	      .expect(200)
	      .then((response) => {
					expect(response.body).toEqual([aBook, anotherBook])
	      })
		})
	})
	
	describe('quando se consulta os livros com um autor', () => {
		beforeEach(() => {
			mockDb.getFilteredBooks.mockResolvedValueOnce([anotherBook])
		})

		it('deve responder com um 200 e todos os livros de um autor', () => {
			return server
	      .get(url)
				.query({ author: 'anotherAuthor' })
	      .expect(200)
	      .then((response) => {
					expect(response.body).toEqual([anotherBook])
	      })
		})
	})
	
	describe('quando se publica um novo livro sem autenticação', () => {
		it('deve responder com um 401 e uma mensagem de erro a dizer que o utilizador não está autenticado', () => {
			return server
	      .post(url)
				.send(book)
	      .expect(401)
	      .then((response) => {
					expect(response.body).toEqual({ error: 'Não autenticado' })
	      })
		})
	})
	
	describe('quando se publica um novo livro autenticado', () => {	
		it('deve responder com um 200 e inserir o livro', () => {
			return server
	      .post('/books')
	      .set(createAuthHeaders('post', url))
				.send(aBook)
	      .expect(200)
	      .then(() => {
					// Verifica se o livro foi inserido
	        expect(db.insertBook).toHaveBeenCalledWith(aBook)
	      })
		})
	})
})
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.decentraland.org/contributor/contributor-pt/guias-para-colaboradores/testing-standards/testing-services-deprecated.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
