Testing Go Applications with Stdin Input
In Go, testing applications that read from stdin can be challenging. Consider a simple application that echoes stdin input to stdout. While it may seem straightforward, writing a test case that verifies the output can pose difficulties.
Failed Attempt
An initial approach would be to simulate stdin and stdout using pipes and manually write to the stdin pipe. However, this may lead to race conditions and unexpected failures.
Solution: Extract Logic and Test Independent Function
Instead of performing all operations in the main function using stdin and stdout, create a separate function that accepts io.Reader and io.Writer as parameters. This approach allows the main function to call the function while the test function directly tests it.
Refactored Code
<code class="go">package main import ( "bufio" "fmt" "io" ) // Echo takes an io.Reader and an io.Writer and echoes input to output. func Echo(r io.Reader, w io.Writer) { reader := bufio.NewReader(r) for { fmt.Print("> ") bytes, _, _ := reader.ReadLine() if bytes == nil { break } fmt.Fprintln(w, string(bytes)) } } func main() { Echo(os.Stdin, os.Stdout) }</code>
Updated Test Case
<code class="go">package main import ( "bufio" "bytes" "io" "os" "testing" ) func TestEcho(t *testing.T) { input := "abc\n" reader := bytes.NewBufferString(input) writer := &bytes.Buffer{} Echo(reader, writer) actual := writer.String() if actual != input { t.Errorf("Wanted: %v, Got: %v", input, actual) } }</code>
This test case simulates the main function by calling the Echo function directly with a buffer for stdin input and a buffer for capturing the output. The captured output is then compared to the expected input, ensuring that the function correctly echoes the input.
The above is the detailed content of How to Test Go Applications That Read from Stdin?. For more information, please follow other related articles on the PHP Chinese website!