在flutter中测试/模拟文件IO

问题描述 投票:0回答:3

我有一个简单的测试:

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 的情况下运行测试?

flutter flutter-test
3个回答
11
投票

经过一些研究,我发现了 google 团队的

file
包,它允许开发人员使用
LocalFileSystem
(基本上是
dart:io
)、
MemoryFileSystem
或自定义
FileSystem

特别是

MemoryFileSystem
甚至自定义
FileSystem
可以在单元和小部件测试中派上用场,因为可以使用它们,因此不会在硬盘上创建文件。因此,在测试运行后创建和清理
FileSystem
会容易得多。

这种方法的缺点是必须将

FileSystem
注入到每个需要访问 FilesDirectories 等的模块中

示例

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,
    );
  });
}

5
投票

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
的模拟对象。


0
投票

考虑使用 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);
  });
}

运行此测试通过,并且不会创建任何额外的文件。

© www.soinside.com 2019 - 2024. All rights reserved.