Testes em Sistemas Distribuídos
Testes unitários por serviço
Tutorial real de testes unitários para Java, Python e Go no monorepo.
Nesta aula você vai
- Escrever testes unitários focados em regra de negócio
- Isolar dependências externas com mocks consistentes
- Executar suíte unitária por serviço com comandos reproduzíveis
Testes unitários por serviço
Nesta aula você vai montar uma base de testes unitários para os serviços customer-service, order-service e payment-service, com foco em comportamento de domínio.
Arquivos usados
services/customer-service/src/main/java/com/amo/customer/service/CustomerService.javaservices/customer-service/src/test/java/com/amo/customer/service/CustomerServiceTest.javaservices/order-service/app/domain/order_service.pyservices/order-service/tests/unit/test_order_service.pyservices/payment-service/internal/service/payment_service.goservices/payment-service/internal/tests/unit/payment_service_test.go
Passo 1 - Defina o contrato de comportamento
Antes de testar framework, descreva cenários de domínio:
- Cliente com e-mail duplicado deve falhar.
- Pedido com item vazio deve falhar.
- Pagamento de pedido cancelado não pode ser autorizado.
Exemplo de regra no Java:
public Customer create(CustomerInput input) {
if (repository.existsByEmail(input.email())) {
throw new BusinessException("EMAIL_ALREADY_EXISTS");
}
return repository.save(Customer.from(input));
}
Passo 2 - Implemente teste unitário no Customer (Java)
Crie CustomerServiceTest.java:
@ExtendWith(MockitoExtension.class)
class CustomerServiceTest {
@Mock CustomerRepository repository;
@InjectMocks CustomerService service;
@Test
void shouldFailWhenEmailAlreadyExists() {
when(repository.existsByEmail("ana@acme.com")).thenReturn(true);
assertThrows(BusinessException.class,
() -> service.create(new CustomerInput("Ana", "ana@acme.com")));
}
}
Comando:
cd services/customer-service
./mvnw -q test -Dtest=CustomerServiceTest
Passo 3 - Implemente teste unitário no Order (Python)
Crie tests/unit/test_order_service.py:
def test_create_order_fails_without_items(order_service):
with pytest.raises(DomainError, match="ORDER_ITEMS_REQUIRED"):
order_service.create_order(customer_id="c-1", items=[])
Comando:
cd services/order-service
pytest tests/unit -q
Passo 4 - Implemente teste unitário no Payment (Go)
Crie internal/tests/unit/payment_service_test.go:
func TestAuthorize_ShouldFailForCancelledOrder(t *testing.T) {
repo := mocks.NewPaymentRepository(t)
svc := service.NewPaymentService(repo)
_, err := svc.Authorize(service.AuthorizeInput{OrderStatus: "CANCELLED"})
require.Error(t, err)
require.Contains(t, err.Error(), "ORDER_CANCELLED")
}
Comando:
cd services/payment-service
go test ./internal/tests/unit/...
Passo 5 - Rode tudo no monorepo
make test-unit
Se o projeto ainda não tiver alvo no Makefile, adicione:
test-unit:
cd services/customer-service && ./mvnw -q test
cd services/order-service && pytest tests/unit -q
cd services/payment-service && go test ./internal/tests/unit/...
Checklist de validação
- Testes não dependem de banco, Kafka ou Redis.
- Nomes dos testes descrevem regra de negócio.
- Falhas exibem código de erro de domínio (
EMAIL_ALREADY_EXISTS,ORDER_ITEMS_REQUIRED). - Execução total em menos de 30 segundos localmente.
Resumo
Você criou uma suíte unitária prática para três linguagens, com comandos reproduzíveis e foco em regra de negócio, preparando terreno para integração e contrato nas próximas aulas.