testing - Rellene os.Stdin para la función que lee de él
go command-line (1)
Burlándose de
os.Stdin
Está en el camino correcto de que
os.Stdin
es una variable (de tipo
*os.File
) que puede modificar, puede asignarle un nuevo valor en las pruebas.
Lo más simple es crear un archivo temporal con el contenido que desea simular como entrada en
os.Stdin
.
Para crear un archivo temporal, use
ioutil.TempFile()
.
Luego escriba el contenido en él y busque de nuevo el comienzo del archivo.
Ahora puede configurarlo como
os.Stdin
y realizar sus pruebas.
No olvides limpiar el archivo temporal.
userInput()
su
userInput()
a esto:
func userInput() error {
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("What is your name?")
var username string
if scanner.Scan() {
username = scanner.Text()
}
if err := scanner.Err(); err != nil {
return err
}
fmt.Println("Entered:", username)
return nil
}
Y así es como puedes probarlo:
func TestUserInput(t *testing.T) {
content := []byte("Tom")
tmpfile, err := ioutil.TempFile("", "example")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tmpfile.Name()) // clean up
if _, err := tmpfile.Write(content); err != nil {
log.Fatal(err)
}
if _, err := tmpfile.Seek(0, 0); err != nil {
log.Fatal(err)
}
oldStdin := os.Stdin
defer func() { os.Stdin = oldStdin }() // Restore original Stdin
os.Stdin = tmpfile
if err := userInput(); err != nil {
t.Errorf("userInput failed: %v", err)
}
if err := tmpfile.Close(); err != nil {
log.Fatal(err)
}
}
Al ejecutar la prueba, vemos una salida:
What is your name?
Entered: Tom
PASS
Vea también la pregunta relacionada sobre burlarse del sistema de archivos: Código de ejemplo para probar el sistema de archivos en Golang
La manera fácil y preferida
También tenga en cuenta que puede refactorizar
userInput()
para que no lea desde
os.Stdin
, sino que podría recibir un
io.Reader
para leer.
Esto lo haría más robusto y mucho más fácil de probar.
En su aplicación, simplemente puede pasarle
os.Stdin
, y en las pruebas puede pasar cualquier
io.Reader
creado / preparado en las pruebas, por ejemplo, usando
strings.NewReader()
,
bytes.NewBuffer()
o
bytes.NewBufferString()
¿Cómo lleno os.Stdin en mi prueba para una función que se lee usando un escáner?
Solicito una entrada de línea de comando de usuario a través de un escáner usando la siguiente función:
func userInput() error {
scanner := bufio.NewScanner(os.Stdin)
println("What is your name?")
scanner.Scan()
username = scanner.Text()
/* ... */
}
Ahora, ¿cómo pruebo este caso y simulo una entrada del usuario? El siguiente ejemplo no funciona. Stdin todavía está vacío.
func TestUserInput(t *testing.T) {
var file *os.File
file.Write([]byte("Tom"))
os.Stdin = file
err := userInput()
/* ... */
}