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) errorfunc(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")funcInsertGitHubWebhook( 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.
No sé en qué ruta debe estar este curso, ahora lo estoy viendo desde la de preparación para el CompTIA Security + pero creo que se mete mucho en GO, me queda la duda si en realidad es realmente importante para la ruta.
Esto es otro mundo :O
Los mocks son objetos simulados que imitan el comportamiento de objetos reales en un entorno controlado, principalmente en las pruebas de software. Permiten a los desarrolladores comprobar si las interacciones con dependencias externas (como bases de datos o APIs) se realizan correctamente sin necesidad de depender de esas implementaciones reales. Esto facilita la identificación de errores y mejora la seguridad, ya que se pueden crear pruebas más robustas y confiables sin afectar el sistema en producción.