2016-07-25 5 views
1

Hat jemand Erfolg gehabt oder irgendwelche Ideen, was wäre der beste Weg, um Eintritt (für Testzwecke) zu einem term.ReadPassword(int(os.Stdin.Fd())) Anruf im golang.org/x/crypto/ssh/terminal Paket verspotten?Mocking crypto/ssh/terminal

Ich habe versucht, eine temporäre Datei zu erstellen (vs os.Stdin) und String-Werte wie testing\n oder testing\r in die temporäre Datei zu schreiben, aber ich erhalte den Fehler inappropriate ioctl for device. Ich vermute es ist etwas, das mit TTY in Verbindung steht oder ein bestimmtes Format, das fehlt (?), Aber ich bin mir nicht ganz sicher.

Hilfe geschätzt.

+0

In welcher Weise versuchen Sie 'terminal.ReadPassword' zu testen? Versuchen Sie, dem Paket einen Test hinzuzufügen? Diese Funktion kann nur auf einem Terminal funktionieren. Wenn Sie kein Terminal haben, verwenden Sie diese Funktion nicht. – JimB

+0

Ich schrieb eine Bibliothek, die diese Funktion verwendet. Ich versuchte einen Test zu erstellen, hauptsächlich um sicherzustellen, dass ich eine vollständige Abdeckung hatte, aber es ist nicht 100% notwendig. Ich benutze 'bufio.Reader' für die normale Eingabe und ich kann die Datei ändern, um diesen Testfall zu behandeln, aber' terminal.ReadPassword' scheint nicht auf die gleiche Weise zu funktionieren. Bibliothek ist hier (nicht als ein Stecker gemeint), falls Sie Vorschläge haben: https://github.com/goposse/tardy – Luke

+0

Sie müssen nur mit ReadPassword bedingte auf ein tty. Sie könnten dies tun, indem Sie es in eine andere Funktion einfügen, einen PasswordReader spotten, wie es Corbin vorgeschlagen hat, oder einfach eine weitere Bedingung hinzufügen, um die if-Anweisung zu überprüfen, ob es sich um IsTerminal handelt. – JimB

Antwort

1

Wenn Sie diesen Test durch Erstellen einer gefälschten Datei, die os.Stdin referenziert, stubbing, werden Ihre Tests ungeheuer Betriebssystem spezifisch, wenn Sie versuchen, zu behandeln. Dies liegt daran, dass Go unter der Haube je nach Betriebssystem separate Syscalls kompiliert. ist implementiert here, aber die Syscalls basierend auf Architektur und Betriebssystem sind in this directory. Wie Sie sehen können, gibt es viele. Ich kann mir keinen guten Weg vorstellen, diesen Test so zu stubben, wie Sie ihn spezifizieren.

Mit dem begrenzten Verständnis des Problems wäre die Lösung, die ich vorschlagen würde eine einfache Schnittstelle entlang der Linien zu injizieren:

type PasswordReader interface { 
    ReadPassword(fd int) ([]byte, error) 
} 

func (pr PasswordReader) ReadPassword(fd int) ([]byte, error) { 
    return terminal.ReadPassword(fd) 
} 

Auf diese Weise können in einem falschen Objekt in den Tests bestehen kann, und Stub die Antwort auf ReadPassword. Ich weiß, das fühlt sich an, als würde man Ihren Code für Ihre Tests schreiben, aber Sie können diesen Gedanken neu definieren, da terminal eine externe Abhängigkeit (I/O) ist, die injiziert werden sollte! Jetzt sorgen Ihre Tests nicht nur dafür, dass Ihr Code funktioniert, sondern helfen Ihnen auch, gute Designentscheidungen zu treffen.

+0

Sinn machen und das hilft auch diesen Teil des Codes aufzuräumen. Danke für den Vorschlag! – Luke