DevOps ‐ Unit Tests - QuantumBitBR/API_5SEM GitHub Wiki

DevOps - Unit Tests

Visão Geral

Conceito

Testes unitários garantem a validação isolada e segura da lógica de negócio das classes de Service.
Cada método de negócio relevante deve possuir cobertura adequada.

Papeis e Deveres nos testes unitáios

  • Quem desenvolve o teste do service é o desenvolvedor da task

  • Caso o teste quebre durante o CI, quem corrige o teste, independente do teste quebrado, é o desenvolvedor dono do PR.

  • Relevância para o projeto

    • Confiança nas alterações de código.

    • Documentação viva da lógica implementada.

    • Detecção precoce de erros e regressões.

    • Facilidade para refatorações seguras.

    • Redução de falhas em produção.


    Implementação

    Stack de Testes Utilizada

    • JUnit 5 (@Test, @BeforeEach)

    • Mockito (@Mock, @InjectMocks, when, verify)

    • AssertJ ou asserções padrão do JUnit

    • Spring Boot Starter Test como dependência principal

    Dependências no pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency>


Estrutura de um Teste Unitário

Fase O que fazer
Arrange Configurar mocks, entradas e expectativas
Act Executar o método a ser testado
Assert Verificar se o comportamento esperado ocorreu

Exemplo Prático

package com.quantum.stratify.services;

import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender;

import static org.mockito.Mockito.; import static org.junit.jupiter.api.Assertions.;

class EmailServiceTest {

private JavaMailSender mailSender;
private EmailService emailService;

@BeforeEach
void setUp() {
    mailSender = mock(JavaMailSender.class);
    emailService = new EmailService(mailSender);
}

@Test
void deveEnviarEmailDeResetDeSenhaComSucesso() {
    // Arrange
    String destino = "[email protected]";
    String novaSenha = "Senha123@";
    ArgumentCaptor&lt;SimpleMailMessage&gt; captor = ArgumentCaptor.forClass(SimpleMailMessage.class);

    // Act
    emailService.enviarEmailSenhaResetada(destino, novaSenha);

    // Assert
    verify(mailSender, times(1)).send(captor.capture());
    SimpleMailMessage mensagemEnviada = captor.getValue();

    assertEquals(destino, mensagemEnviada.getTo()[0]);
    assertEquals("Reset de senha - Stratify", mensagemEnviada.getSubject());
    assertTrue(mensagemEnviada.getText().contains(novaSenha));
}

}


Regras Gerais para Testes de Services

  • Isolar dependências usando @Mock.

  • Não testar repositórios (JpaRepository) — responsabilidade dos testes de integração.

  • Nome dos métodos de teste deve ser descritivo (em português ou inglês padronizado):

    • deveCalcularTempoMedioPorProjeto()

    • shouldReturnProjectListByUserId()

  • Evitar chamadas reais a banco de dados ou SMTP — apenas mocks.


Diagrama de Fluxo de um Teste Unitário

flowchart TD
    A[Início do Teste Unitário] --> B[Arrange: Configurações e Mocks]
    B --> C[Act: Execução do método testado]
    C --> D[Assert: Verificação dos resultados]
    D --> E{Resultado esperado?}
    E -- Sim --> F[Teste passa ✅]
    E -- Não --> G[Teste falha ❌]
    F --> H[Fim do Teste]
    G --> H

Exemplos de Implementação no Projeto

  • EmailServiceTest

  • FatoEficienciaUserStoryServiceTest

  • UsuarioServiceTest


Benefícios para o Projeto

  • Maior confiança em releases.

  • Documentação viva da lógica implementada.

  • Facilidade na manutenção e expansão do código.

  • Redução de falhas em produção.


Observação Importante

Para regras de negócio mais complexas, crie um teste para cada cenário relevante, assegurando cobertura ampla dos comportamentos possíveis. Caso exija dúvidas sobre a criação de cenários relevantes, consultar o PO.


Testes Unitários no Frontend com Vitest

🔍 Por que executar esses testes?

  • As requisições aos serviços de backend sejam chamadas corretamente

  • Os parâmetros enviados estão completos e no formato esperado

  • A lógica de cada serviço esteja funcionando de forma isolada e previsível

  • Refatorar com segurança, sem medo de quebrar a integração frontend-backend

🛠️ Tecnologias Utilizadas

  • Vitest

  • vi.mock()

📁 Estrutura de Pastas Recomendadas

src/
├── services/
│   ├── AverageTimeService.ts
│   └── StatusService.ts

tests/ └── services/ ├── AverageTimeService.spec.ts └── StatusService.spec.ts

🔪 Exemplos de Testes com Vitest

AverageTimeService.spec.ts

import { describe, it, expect, vi, beforeEach } from 'vitest'
import AverageTimeService from '@/services/AverageTimeService'
import { api } from '@/services/apiConfig'

vi.mock('@/services/apiConfig', () => ({ api: { get: vi.fn() } }))

describe('AverageTimeService', () => { beforeEach(() => { vi.clearAllMocks() })

it('deve buscar tempo médio com os parâmetros corretos', async () => { (api.get as any).mockResolvedValue({ data: { tempoMedio: 4.5 } })

const result = await AverageTimeService.getAverageTime(1, 2)

expect(api.get).toHaveBeenCalledWith('/fatoeficiencia/tempo-medio', {
  params: { projetoId: 1, usuarioId: 2 }
})
expect(result.tempoMedio).toBe(4.5)

}) })

StatusService.spec.ts

import { describe, it, expect, vi, beforeEach } from 'vitest'
import StatusService from '@/services/StatusService'
import { api } from '@/services/apiConfig'

vi.mock('@/services/apiConfig', () => ({ api: { get: vi.fn() } }))

describe('StatusService', () => { beforeEach(() => { vi.clearAllMocks() })

it('deve buscar percentual por status com projeto e usuário', async () => { const mockData = [{ nomeStatus: 'Em Andamento', percentual: 70 }] ;(api.get as any).mockResolvedValue({ data: mockData })

const result = await StatusService.quantityPerStatus(10, 20)

expect(api.get).toHaveBeenCalledWith('/userStory/percentual-por-status', {
  params: { projetoId: 10, usuarioId: 20 }
})
expect(result).toEqual(mockData)

}) })

⚖️ Como configurar o projeto para usar o Vitest

1. Instale as dependências:

npm install -D vitest @vitest/ui

2. Configure o vite.config.ts:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({ plugins: [vue()], test: { globals: true, environment: 'jsdom', coverage: { reporter: ['text', 'json', 'html'] } } })

3. Adicione os scripts no package.json:

"scripts": {
  "test": "vitest",
  "test:ui": "vitest --ui"
}

4. Rode os testes:


npm install -D vitest @vitest/ui @vitejs/plugin-vue
npm install -D @vitest/coverage-v8
npm run test
⚠️ **GitHub.com Fallback** ⚠️