test mock golang create benchmark unit-testing go

unit testing - mock - ¿Hay una manera fácil de perder el tiempo? ¿Ahora() globalmente en Golang durante la prueba?



golang test assertions (5)

Parte de nuestro código es sensible al tiempo y necesitamos poder reservar algo y luego liberarlo en 30-60 segundos, etc., en el que solo podemos hacer una time.Sleep(60 * time.Second)

Acabo de implementar la interfaz de tiempo y, durante la prueba, uso una implementación de la interfaz de tiempo, similar a esta discusión de golang-nuts .

Sin embargo, se llama a time.Now() en varios sitios, lo que significa que debemos pasar una variable para realizar un seguimiento de cuánto tiempo hemos dormido.

Me preguntaba si hay una forma alternativa de apagar el time.Now() globalmente. Tal vez hacer una llamada al sistema para cambiar el reloj del sistema?

¿Quizás podamos escribir nuestro propio paquete de tiempo que básicamente envuelve el paquete de tiempo pero nos permite cambiarlo?

Nuestra implementación actual funciona bien, soy principiante y tengo curiosidad por ver si alguien tiene otras ideas.


Además, si solo necesita marcar el time.Now . time.Now puede inyectar la dependencia como una función, por ejemplo,

func moonPhase(now func() time.Time) { if now == nil { now = time.Now } // use now()... } // Then dependent code uses just moonPhase(nil) // And tests inject own version stubNow := func() time.Time { return time.Unix(1515151515, 0) } moonPhase(stubNow)

Concedido todo lo que es un poco feo si proviene del fondo de idiomas dinámicos (por ejemplo, Ruby) :(


Con la implementación de una interfaz personalizada, ya está en el camino correcto . Supongo que utiliza el siguiente consejo del hilo de golang nuts que ha publicado:

type Clock interface { Now() time.Time After(d time.Duration) <-chan time.Time }

y proporcionar una implementación concreta.

type realClock struct{} func (realClock) Now() time.Time { return time.Now() } func (realClock) After(d time.Duration) <-chan time.Time { return time.After(d) }

y una implementación de prueba.

Original

Cambiar la hora del sistema mientras se hacen las pruebas (o en general) es una mala idea . No sabes qué depende de la hora del sistema mientras ejecutas las pruebas y no quieres descubrirlo de la mejor manera al pasar días depurando en eso. Simplemente no lo hagas.

Tampoco hay forma de hacer sombra en el paquete de tiempo a nivel mundial y hacer eso no haría nada más que no podría hacer con la solución de interfaz. Puede escribir su propio paquete de tiempo que utiliza la biblioteca estándar y proporciona una función para cambiar a una biblioteca de tiempo simulado para realizar pruebas si es el objeto de tiempo que necesita para compartir con la solución de interfaz que lo está molestando.

La mejor manera de diseñar y probar su código sería probablemente hacer que el código sea lo más apátrida posible. Divide tu funcionalidad en partes comprobables y sin estado. Probar estos componentes por separado es mucho más fácil entonces. Además, menos efectos secundarios significa que es mucho más fácil hacer que el código se ejecute simultáneamente.


Del resultado de Google encontré una solución relativamente simple: Here

La idea básica es usar otra función llamada "nowFunc" para obtener el tiempo. Ahora (). En su principal, inicialice esta función para devolver el tiempo. Ahora (). En su prueba, inicialice esta función para devolver un tiempo falso fijo.


Si los métodos que necesita para simularse son pocos, como Now() , puede crear una variable de paquete que se puede sobrescribir con las pruebas:

package foo import "time" var Now = time.Now // The rest of your code...which calls Now() instead of time.Now()

entonces en su archivo de prueba:

package foo import ( "testing" "time" ) var Now = func() time.Time { return ... } // Your tests


Uso el paquete bouk / monkey para reemplazar el time.Now() llama en mi código con un falso:

package main import ( "fmt" "time" "github.com/bouk/monkey" ) func main() { wayback := time.Date(1974, time.May, 19, 1, 2, 3, 4, time.UTC) patch := monkey.Patch(time.Now, func() time.Time { return wayback }) defer patch.Unpatch() fmt.Printf("It is now %s/n", time.Now()) }

Esto funciona bien en las pruebas para falsificar las dependencias del sistema y evita el patrón DI abusado . El código de producción se mantiene separado del código de prueba y usted obtiene un control útil de las dependencias del sistema.