如何为Go语言中的嵌套输入场景编写单元测试
问题
我有一个使用os.Stdin获取用户输入的函数:
func (i input) GetInput(stdin io.Reader) (string, error) { reader := bufio.NewReader(stdin) data, err := reader.ReadString('\n') if err != nil { return "", fmt.Errorf("get input error: %w", err) } return strings.ReplaceAll(data, "\n", ""), nil }
程序中需要实现两次输入逻辑:
- 第一次获取基础信息(比如用户名)
- 第二次获取依赖于首次输入的附加信息
核心业务逻辑如下:
name, err := GetInput(os.Stdin) if err != nil { // 错误处理..... } switch name { case "test": // 执行操作... age, err := GetInput(os.Stdin) if err != nil { // 错误处理..... } fmt.Println(age) case "another": // 此处为另一个输入操作 }
我目前能通过以下代码测试单次用户输入场景:
var stdin bytes.Buffer stdin.Write([]byte(fmt.Sprintf("%s\n", tt.input))) GetInput(stdin)
但这种方法无法适配嵌套输入的测试场景,想问下是否能为这种嵌套输入的场景编写单元测试?
解决方案
完全可以实现嵌套输入场景的单元测试,核心思路是在模拟的bytes.Buffer中按输入顺序写入所有需要的内容,用换行符分隔每一次输入即可。因为bufio.Reader会按顺序读取缓冲区中的内容,每次调用ReadString('\n')都会读取到下一个换行符前的内容,刚好匹配多次输入的场景。
测试示例代码
针对name为test时需要输入age的场景,测试代码可以这么写:
import ( "bytes" "fmt" "testing" ) // 假设你的业务逻辑封装在一个函数里,比如HandleUserInput func HandleUserInput(stdin io.Reader) { name, err := GetInput(stdin) if err != nil { return } switch name { case "test": age, err := GetInput(stdin) if err != nil { return } fmt.Println(age) case "another": // 其他逻辑 } } func TestHandleUserInputWithNestedInput(t *testing.T) { // 模拟两次输入:第一次是"test",第二次是"25",用换行分隔 var stdin bytes.Buffer stdin.WriteString("test\n25\n") // 调用业务逻辑函数,传入模拟的输入 HandleUserInput(&stdin) // 若需验证输出,可重定向os.Stdout到bytes.Buffer,读取后断言结果 }
关键说明
- 模拟输入时,必须按实际交互顺序写入内容,每个输入后加换行符
\n,和用户终端输入行为一致。 - 测试不同分支(比如
name为another的场景)时,只需调整缓冲区内容,例如写入another\nxxx\n。 - 如需验证输出结果,可通过重定向
os.Stdout到bytes.Buffer,读取缓冲区内容做断言。
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

