Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing/mocking file IO in flutter

I have a simple test:

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

It freezes after printing 1. I know that Flutter runs test in fake-async zones and I know that I am required to run code with real IO with runAsync.

However, is it also possible somehow to inject a mock IO filesystem and run the tests without runAsync?

like image 431
user3612643 Avatar asked Oct 15 '22 04:10

user3612643


1 Answers

After doing some research I found the file package from the google team which allows developers to use the LocalFileSystem (basically dart:io), a MemoryFileSystem or a custom FileSystem.

Especially the MemoryFileSystem or even the custom FileSystem could come in handy for unit and widget tests since these can be used so no files are created on the hard drive. Therefore, it is a lot easier to create and cleanup the FileSystem after a test has run.

The drawback of this approach is that one has to inject the FileSystem into every module requiring access to Files, Directories, etc.

Example

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

Test code

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,
    );
  });
}
like image 171
Jens Avatar answered Oct 19 '22 02:10

Jens