我有一个简单的测试:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
Future<void> main() async {
testWidgets(
'Simple empty test',
(WidgetTester tester) async {
print("1");
await Directory('/tmp').exists();
print("2");
await tester.pumpWidget(Container());
},
);
}
打印后冻结
1
。我知道 Flutter 在假异步区域中运行测试,并且我知道我需要使用 runAsync 来运行具有真实 IO 的代码。
但是,是否也可以以某种方式注入模拟 IO 文件系统并在没有 runAsync 的情况下运行测试?
file
包,它允许开发人员使用 LocalFileSystem
(基本上是 dart:io
)、MemoryFileSystem
或自定义 FileSystem
。
特别是
MemoryFileSystem
甚至自定义 FileSystem
可以在单元和小部件测试中派上用场,因为可以使用它们,因此不会在硬盘上创建文件。因此,在测试运行后创建和清理 FileSystem
会容易得多。
这种方法的缺点是必须将
FileSystem
注入到每个需要访问 Files、Directories 等的模块中
示例
import 'package:file/file.dart';
class DirectoryOperator {
final FileSystem fileSystem;
// Inject implementation of the FileSystem
DirectoryOperator({required this.fileSystem});
Future<void> methodOperatingOnFileSystem(String path) async {
Directory directory = fileSystem.directory(path);
await directory.create(recursive: true);
}
}
测试代码
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_test/flutter_test.dart';
main() {
test('$DirectoryOperator creates directory on path', () async {
FileSystem fileSystem = MemoryFileSystem();
var systemUnderTest = DirectoryOperator(fileSystem: fileSystem);
String testPath = 'Path/to/dir';
await systemUnderTest.methodOperatingOnFileSystem(testPath);
bool doesDirectoryExist = await fileSystem.directory(testPath).exists();
expect(
doesDirectoryExist,
isTrue,
);
});
}
I/O 操作可以使用 mockito 和
IOOverrides
: 进行模拟
import 'dart:io';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
import 'test.mocks.dart';
class TestFile extends MockFile {
final String _path;
TestFile(this._path) {
when(readAsStringSync()).thenReturn('(string from $_path)');
}
}
@GenerateMocks([File])
void main() {
test('I/O overrides', () {
IOOverrides.runZoned(() {
expect(File('path/to/a').readAsStringSync(), '(string from path/to/a)');
expect(File('path/to/b').readAsStringSync(), '(string from path/to/b)');
}, createFile: (String path) => TestFile(path));
});
}
上面的示例使用
IOOverrides
来挂钩 File
对象的创建,并返回一个类似 File
的模拟对象。
考虑使用 file 库,由 google 发布。
示例:
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
test('create empty text file', () {
final FileSystem mockFileSystem = MemoryFileSystem();
final File file = mockFileSystem.file('generated/hello_world.txt');
file.createSync(recursive: true);
expect(file.existsSync(), true);
});
}
运行此测试通过,并且不会创建任何额外的文件。