Middle
Que testes escreve e de que forma?
sobes.tech IA
Resposta da IA
Escrevo os seguintes tipos de testes:
- Testes unitários: Testam componentes ou métodos individuais de uma classe isoladamente do resto do sistema. Uso JUnit ou TestNG. Para simular dependências, Mockito.
- Testes de integração: Testam a interação entre vários componentes, subsistemas ou serviços. Por exemplo, interação com bases de dados ou API externas. Uso Spring Boot Test para testar aplicações Spring, Testcontainers para testes com dependências reais (bases de dados, brokers de mensagens).
- Testes de componentes / Testes End-to-End (E2E): Testam o sistema do ponto de vista do utilizador de princípio a fim. Geralmente, testes automatizados de interface de utilizador ou API. Para API uso Rest-Assured. Para UI, Selenium (embora prefira escrever testes API, pois são mais estáveis e rápidos).
Processo de escrita de testes:
- Escolha do framework: JUnit 5 ou TestNG para testes unitários, Spring Boot Test, Rest-Assured, Testcontainers para testes de integração e componentes.
- Escrever testes antes ou durante a escrita do código: Uso TDD (Desenvolvimento orientado por testes) ou escrevo testes logo após escrever a funcionalidade.
- Isolamento dos testes: Para testes unitários, uso Mockito para simular dependências, de modo a testar apenas um componente isolado.
- Estrutura do teste: Normalmente sigo a estrutura Arrange-Act-Assert (Preparar dados, Executar ação, Verificar resultado).
- Nomenclatura clara dos testes: Os nomes dos testes devem descrever claramente o que é testado e sob que condições. Por exemplo,
userService_createUser_shouldSaveUserInDatabase. - Testar condições limite e erros: Verifico tanto cenários normais quanto casos com dados de entrada incorretos, exceções e valores limite.
- Refatoração dos testes: Mantenho os testes limpos e legíveis, assim como o código principal.
Exemplo de teste unitário com Mockito e JUnit 5:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock // Dependência que simulamos
private UserRepository userRepository;
@InjectMocks // Serviço que estamos a testar
private UserService userService;
@Test
void createUser_shouldSaveUserInDatabase() {
// Arrange: Preparar dados e simular comportamento
User user = new User("Alice", "alice@example.com");
when(userRepository.save(any(User.class))).thenReturn(user); // Simular método save do repositório
// Act: Executar a ação que estamos a testar
User createdUser = userService.createUser(user);
// Assert: Verificar resultado
assertEquals("Alice", createdUser.getName()); // Verificar se o usuário foi criado com o nome correto
verify(userRepository, times(1)).save(any(User.class)); // Verificar se o método save foi chamado exatamente uma vez
}
}
Exemplo de uso do Rest-Assured para teste de API de integração:
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.equalTo;
class UserControllerIntegrationTest {
@BeforeAll
static void setup() {
// Configuração da URL base para os testes
RestAssured.baseURI = "http://localhost:8080";
RestAssured.port = 8080;
}
@Test
void getUserById_shouldReturnUser() {
// Executar e verificar resposta
given()
.when()
.get("/users/1") // URL para obter usuário por ID
.then()
.statusCode(200) // Verificar código de status
.body("name", equalTo("John Doe")); // Verificar valor no corpo da resposta
}
}