- 
                Notifications
    You must be signed in to change notification settings 
- Fork 1
DevOps ‐ Unit Tests
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.
- 
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. 
- 
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. 
- 
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 
<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>
| 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 | 
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 = "usuario@teste.com";
    String novaSenha = "Senha123@";
    ArgumentCaptor<SimpleMailMessage> 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));
}
}
- 
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. 
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
- 
EmailServiceTest
- 
FatoEficienciaUserStoryServiceTest
- 
UsuarioServiceTest
- 
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. 
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.
- 
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 
- 
Vitest 
- 
vi.mock() 
src/
├── services/
│   ├── AverageTimeService.ts
│   └── StatusService.ts
tests/
└── services/
├── AverageTimeService.spec.ts
└── StatusService.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)
})
})
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)
})
})
npm install -D vitest @vitest/ui
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']
}
}
})
"scripts": {
  "test": "vitest",
  "test:ui": "vitest --ui"
}
npm install -D vitest @vitest/ui @vitejs/plugin-vue
npm install -D @vitest/coverage-v8
npm run test