Solución:
Sí, con una simple refactorización. Crear un zSomeFunc
variable de tipo de función, inicializada con z.SomeFunc
y haz que tu paquete llame a eso en lugar de z.SomeFunc()
:
var zSomeFunc = z.SomeFunc
func abc() {
// ...
v := zSomeFunc()
// ...
}
En las pruebas, puede asignar otra función a zSomeFunc
, uno que se define en las pruebas y hace lo que la prueba quiere.
Por ejemplo:
func TestAbc(t *testing.T) {
// Save current function and restore at the end:
old := zSomeFunc
defer func() { zSomeFunc = old }()
zSomeFunc = func() int {
// This will be called, do whatever you want to,
// return whatever you want to
return 1
}
// Call the tested function
abc()
// Check expected behavior
}
Ver relacionado / posible duplicado: Prueba de escenarios de salida del sistema operativo en Go con información de cobertura (coveralls.io/Goveralls)
Una cosa que puedes hacer es esto:
import "x/y/z"
var someFunc = z.SomeFunc
func abc() {
...
v := someFunc()
...
}
Y en tu archivo de prueba harías esto.
func Test_abc() {
someFunc = mockFunc
abc()
}
Pero asegúrese de hacer esto de manera simultánea, si tiene múltiples TestXxx
funciones llamando abc
o entorno someFunc
puede ser mejor usar un struct
con un someFunc
campo.
Tener un puntero de función y un mono parcheándolo es el de hacerlo. Pero luego, cuando tenga múltiples funciones para simular, tendrá un puntero de función numérico e innecesariamente tendrá que llamar a la función usando solo el puntero de función.
La idea mejor y recomendada es tener una interfaz y hacer que su función sea parte de la estructura que implementa la interfaz. Una vez hecho esto, puede generar simulacros usando algunas buenas herramientas disponibles para usar.
He estado usando esto:
mockgen -source myModule.go -package myPackage -destination myModuleMock.go
Puede instalarlo de la siguiente manera:
got get github.com/golang/mock