Pruebas unitarias de una función que inicia una goroutine dentro de ella.
Tengo una base de código que es aproximadamente así:
type Service struct {
Repo repo // Una interfaz que contiene tanto FunctionOne como FunctionTwo
GoRoutineWaitgroup *sync.WaitGroup
}
func (impl *Service) MyFunction(s string) bool {
a := impl.Repo.FunctionOne()
b := impl.Repo.FunctionTwo()
fmt.Println(“Ejecutado función Uno y Dos”)
go impl.validateMyFunction(a,b)
return true
}
func (impl *Service) validateMyFunction(a string,b string) {
defer helpers.PanicHandler()
impl.GoRoutineWaitgroup.Add(1)
defer impl.GoRoutineWaitgroup.Done()
fmt.Println("a y b han sido validados")
}
Y escribí pruebas unitarias algo similares a esto.
func TestMyFunction(t *testing.T) {
ms := &Service{}
test := []struct{
input string
output bool
case string
}{
{"a", true, "muestra"}
}
}
for _, test := range tests {
t.Run(test.case, func(t *testing.T) {
mockRepo := new(mockrepo.Repo) // mockRepo contiene burlas de los métodos de la capa de repo original generados utilizando mockery con fines de prueba
mockRepo.On("FunctionOne")
mockRepo.On("FunctionTwo")
ms.Repo = mockRepo
op := ms.MyFunction(test.input)
assert.Equal(t, test.Output, op)
})
}
} // Tenga en cuenta que este no es mi código real, sino solo una estructura básica.
Todas las pruebas son exitosas. Pero al ejecutar el comando go test -v, vi múltiples lugares en el código donde el programa se bloqueó y dio una dirección de memoria invalida o una referencia de puntero nulo. Verifiqué el código en modo de depuración y me di cuenta de que el problema está en impl.GoRoutineWaitgroup.Add (1) en el método validateMyFunction y cuando comenté go validateMyFunction (a, b) y volví a ejecutar las pruebas, no hubo panico en los registros. Entonces, ¿cómo resuelvo este problema? ¿Cómo manejar las pruebas unitarias de las funciones donde iniciamos un goroutine desde adentro (como en este caso)?
davy.ai
Puede resolver este problema inicializando el
GoRoutineWaitgroup
en la estructuraService
. Esto se puede hacer agregando la siguiente línea de código a la estructuraService
:Go
GoRoutineWaitgroup *sync.WaitGroup = &sync.WaitGroup{}
Esto garantizará que el
GoRoutineWaitgroup
esté inicializado antes de que se llame al métodovalidateMyFunction
.Cuando se prueban unidades de funciones que inician una goroutine, debe asegurarse de que la goroutine esté inicializada adecuadamente y que los recursos necesarios estén disponibles.