Creando mocks con Testify para commits

Clase 6 de 30Curso de Ciberseguridad para Desarrollo Web

Resumen

Crear software seguro empieza por poder probarlo bien. Aquí verás cómo usar mocks con Testify en Go para testear un repository de commits sin depender de una base de datos. La idea clave: más testabilidad, menos riesgos de seguridad, porque detectas bugs y brechas antes.

¿Por qué mocks mejoran la seguridad y el testeo en Go?

Los mocks simplifican las pruebas de integraciones como bases de datos. Al simular respuestas controladas:

  • Validas flujos felices y fallos de la BD con facilidad.
  • Haces assertions sobre llamadas y parámetros.
  • Aceleras el ciclo de feedback sin infra real.
  • Reduces riesgos: código más testeable = menos bugs y brechas.

La librería usada es Testify y su módulo de mock. Se instala con go get y se importa desde el repository de commits.

go get github.com/stretch/testify/mock

¿Cómo crear mocks con Testify/mock en el repository?

Partimos de una interfaz de commit en la carpeta "repository" y agregamos un archivo commits/mock.go. La estructura del mock implementa la interfaz para poder simular operaciones.

¿Qué estructura define el mock?

Creamos un paquete repository y una estructura mockCommit con un campo a mock.Mock que gestionará dependencias, llamadas y valores de retorno.

package repository import ( "context" "github.com/stretch/testify/mock" // importa los paquetes reales de tu proyecto: // "tu/modulo/entity" ) type mockCommit struct { mock.Mock }

¿Cómo se implementan los métodos con assertions y retornos?

Se copian los métodos de la interfaz commit y se agregan dos líneas por método: una para registrar la llamada y otra para el retorno. Así simulas éxitos y fallos de la BD.

// Simula: Insert(ctx, commit) error func (m *mockCommit) Insert(ctx context.Context, c entity.Commit) error { args := m.Called(ctx, c) // assertions de parámetros. return args.Error(0) // retorna el error en el índice 0. } // Simula: GetByEmail(ctx, email) (entity.Commit, error) func (m *mockCommit) GetByEmail(ctx context.Context, email string) (entity.Commit, error) { args := m.Called(ctx, email) // assertions de parámetros. commit := args.Get(0).(entity.Commit) // primer valor. return commit, args.Error(1) // segundo valor: error. }
  • Con m.Called(...) validas que se invocó con los argumentos esperados.
  • Con args.Get(i) y args.Error(i) controlas los retornos.
  • Puedes simular fallos de BD devolviendo errores programados.

¿Cómo insertar un GitHub webhook en un commit testable?

Se implementa un método alto nivel para construir un entity.Commit desde un webhook de GitHub y delegar el guardado al repository. Recibe context, el repo de commits y el webhook desde models.

¿Qué datos del webhook construyen el commit?

A partir del repository.full_name y del head_commit del webhook se llenan campos clave. También se guarda el payload completo en un body y se setean createdAt y updatedAt con time.

package main import ( "context" "time" // "tu/modulo/models" // "tu/modulo/entity" // "tu/modulo/repository" ) func InsertGitHubWebhook( ctx context.Context, repo repository.Commit, // interfaz commit del repository. webhook models.GitHubWebhook, // antes llamado pushEvent; se usa githubWebhook. ) error { createdTime := time.Now() c := entity.Commit{ Repo: webhook.Repository.FullName, CommitID: webhook.HeadCommit.ID, Message: webhook.HeadCommit.Message, Author: webhook.HeadCommit.Author.Username, Email: webhook.HeadCommit.Author.Email, Body: string(webhook.Body), // payload completo como string. CreatedAt: createdTime, UpdatedAt: createdTime, } return repo.Insert(ctx, c) }
  • No se asigna ID: lo autogenera la capa de datos.
  • Se captura FullName, ID, Message, Username y Email desde el head_commit.
  • Body guarda el payload completo del webhook como cadena.
  • CreatedAt y UpdatedAt usan el mismo createdTime de time.

¿Cómo se testea este método con mocks?

  • Configura el mock para Insert(ctx, commit) retornando nil o un error.
  • Verifica con assertions que se invocó con el commit construido.
  • Simula fallos para observar el manejo de errores y cubrir ramas.

Claves que debes recordar:

  • Interfaz commit: desacopla la lógica de negocio de la persistencia.
  • Mocks con Testify: github.com/stretch/testify/mock para assertions y retornos controlados.
  • go get: trae el módulo del mock rápidamente.
  • context: se pasa en cada operación para control y cancelación.
  • Seguridad: código más testeable reduce la superficie de fallos explotables.

¿Te gustaría ver casos de prueba que automaticen estos mocks y ver reportes de fallos? Cuéntame qué escenario te interesa cubrir primero.