如何在Dart测试中模拟用户输入?
在Dart测试中模拟命令行用户输入,验证输入合法性
要测试依赖readLineSync的命令行工具,核心是替换标准输入(stdin)的数据源,用模拟的输入流代替用户实际输入。以下是具体实现步骤和测试示例:
1. 封装待测试的选择函数
先把选择逻辑封装成独立函数,方便测试:
import 'dart:io'; int selectFromList(List<String> options) { print('请选择选项(输入数字索引):'); for (var i = 0; i < options.length; i++) { print('$i: ${options[i]}'); } while (true) { final input = stdin.readLineSync(); if (input == null) { print('输入无效,请重试'); continue; } final parsed = int.tryParse(input); if (parsed == null) { print('请输入有效整数'); continue; } if (parsed < 0 || parsed >= options.length) { print('输入超出范围,请输入0到${options.length - 1}之间的数字'); continue; } return parsed; } }
2. 编写测试用例(使用test.dart)
测试时通过stdin.addStream注入模拟输入内容,每个输入后加换行符\n模拟用户按回车的操作。同时要在测试前后恢复stdin状态,避免影响其他测试。
import 'dart:convert'; import 'dart:io'; import 'package:test/test.dart'; void main() { late IOSink originalStdout; late Stream<List<int>> originalStdin; setUp(() { // 保存原始标准输入输出,测试后恢复 originalStdout = stdout; originalStdin = stdin; // 重定向stdout到空,避免测试打印干扰 stdout = IOSink(NullSink()); }); tearDown(() { // 恢复原始标准输入输出 stdout = originalStdout; stdin = originalStdin; }); test('拒绝过小的整数输入,最终返回有效索引', () { // 模拟输入:-1 → 0 const mockInput = '-1\n0\n'; stdin.addStream(Stream.value(utf8.encode(mockInput))); final result = selectFromList(['选项A', '选项B']); expect(result, 0); }); test('拒绝过大的整数输入,最终返回有效索引', () { // 模拟输入:3 → 1 const mockInput = '3\n1\n'; stdin.addStream(Stream.value(utf8.encode(mockInput))); final result = selectFromList(['选项A', '选项B']); expect(result, 1); }); test('多次无效输入后返回有效索引', () { // 模拟输入:abc → 2 → 1 const mockInput = 'abc\n2\n1\n'; stdin.addStream(Stream.value(utf8.encode(mockInput))); final result = selectFromList(['选项A', '选项B']); expect(result, 1); }); }
关键说明
- 模拟输入流:用
utf8.encode把字符串转成字节流,每个输入后加\n,对应用户输入完按回车的操作。 - 隔离测试环境:在
setUp和tearDown中保存并恢复原始的stdin和stdout,避免测试间互相干扰;重定向stdout到空,防止测试时的打印输出污染测试报告。 - 验证逻辑:通过注入不同输入组合,验证函数能否正确拒绝无效输入(非整数、超出范围),直到获取有效输入后返回正确结果。
内容的提问来源于stack exchange,提问作者JasonTS
相关产品推荐
相关产品推荐

