40

File can be read from the directory relative to the dart script file, simply as var file = new File('./fixture/contacts.json').

However the file cannot be read flutter test running inside IDE.

Loading as resource (it is not, since I do not want to bundle the test data file in the app) also does not work in test.

What is a good way to read file in flutter (for both command line test and IDE test)?

Running flutter test is very fast. However testing inside Intellij IDE is ver slow, but it can set debug breakpoint and step into and view variables. So both testing is very useful.

Kyaw Tun
  • 12,447
  • 10
  • 56
  • 83

10 Answers10

54

Just had a go at this and it's easier than you might expect.

First, create a folder that lives in the same directory than your tests are. For example, I created a folder called test_resources.

Test resources folder structure.

Then, let's say we have the following JSON file for testing purposes.

test_resources/contacts.json

{
  "contacts": [
    {
      "id": 1,
      "name": "Seth Ladd"
    },
    {
      "id": 2,
      "name": "Eric Seidel"
    }
  ]
}

test/load_file_test.dart

We could use it for our test like so:

import 'dart:convert';
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';

void main() {
  test('Load a file', () async {
    final file = new File('test_resources/contacts.json');
    final json = jsonDecode(await file.readAsString());
    final contacts = json['contacts'];

    final seth = contacts.first;
    expect(seth['id'], 1);
    expect(seth['name'], 'Seth Ladd');

    final eric = contacts.last;
    expect(eric['id'], 2);
    expect(eric['name'], 'Eric Seidel');
  });
}
Iiro Krankka
  • 4,959
  • 5
  • 38
  • 42
  • 4
    Is it just me or this structure doesn't work when running `flutter test`? Works in IDE though. Anyone set up for working in both: command-line and IDE? – Ikar Pohorský Jul 03 '19 at 13:18
  • 2
    @IkarPohorský take a look at Grahambo's answer. I had similar issue to you and his answer fixed it for me. – Cam Aug 07 '19 at 14:33
  • 1
    I prefer create resources directory inside test directory. In this way I can get the resource file with this path test/resources/contacts.json and I can keep all the test files insid test. – bl4ckr0se Aug 25 '20 at 13:36
  • 1
    @liroKrankka above method works for mobile & desktop but what about loading json file for flutter-web as 'dart:io' doesn't support browser to access disk system. – Rajesh Patil Jan 03 '22 at 08:18
  • 1
    For me this is not working ```FileSystemException: Cannot open file, path = 'test_resources/contacts.json' (OS Error: No such file or directory, errno = 2)``` – Bawantha Aug 26 '22 at 08:57
12

I encountered this same issue today. My tests passed in my IDE (Android Studio) but failed on CI. I found that the IDE wanted a non-relative path but flutter test wants a relative path. I think this is a bug and I'll be looking for the right place to report it. However, I found a crude work around for the meantime. Basically, I have a function which tries both ways to specify the file path..

import 'dart:convert';
import 'dart:io';

Future<Map<String, dynamic>> parseRawSample(String filePath,
    [bool relative = true]) async {
  filePath = relative ? "test_data/src/samples/raw/$filePath" : filePath;

  String jsonString;
  try {
    jsonString = await File(filePath).readAsString();
  } catch (e) {
    jsonString = await File("../" + filePath).readAsString();
  }
  return json.decode(jsonString);
}

much of that code is specific to my situation, but I think others could probably adapt this work around for their purposes.

Grahambo
  • 467
  • 5
  • 11
7

i created an util because vscode and command line test base path is different

https://github.com/terryx/flutter-muscle/blob/master/github_provider/test/utils/test_path.dart

this is how i use it

https://github.com/terryx/flutter-muscle/blob/master/github_provider/test/services/github_test.dart#L13


Another way is to specify exact test path in command line

$ flutter test test
Terry
  • 1,470
  • 13
  • 15
4

The current directory is always the project root in Flutter 2.0 So you can now read files with the same code on the command line and in the IDE.

https://github.com/flutter/flutter/pull/74622

macoshita
  • 41
  • 1
4

A simple solution would be

import 'dart:io';

String fixture(String name) => File('test/fixtures/$name').readAsStringSync();

test folder is at the same level as the lib folder, and you can access the fixture like this: String fileContent = fixture('contacts.json')

after that typically convert fileContent to Map object with jsonDecode from dart:convert and then map this converted object to your desired model which typically has myModel.fromJson(Map onvertedJson) method.

You can generate your model from JSON responses with json to dart android studio plugin or use online converter tools like this online JSON converter

zex_rectooor
  • 692
  • 7
  • 26
3

Just use the Directory.current.path and you are good to go:

import 'dart:io';


// Set the absolute path for your file
final path = '${Directory.current.path}/test/example.json'; 
final json = await File(path).readAsString();
Danilo Rêgo
  • 539
  • 5
  • 4
0

You can just put your test files in two places (I know it is not a good practice to have the same data in two places). Let's say I want to have data.json file to be opened in code under tests with final file = File(dataFilename), then dataFilename will be 'test_resources/data.json'. If test is executed from Android Studio, test_resources is a folder in project root. If tests are executed from command line test_resources is a folder in test folder. So placing the file in both places will solve the problem.

Valentina Konyukhova
  • 4,464
  • 2
  • 24
  • 33
0

Just copying the solution from Flocbit: https://github.com/flutter/flutter/issues/20907#issuecomment-557634184

String fixture(String name) {
   var dir = Directory.current.path;
   if (dir.endsWith('/test')) {
     dir = dir.replaceAll('/test', '');
   }
   return File('$dir/test/fixtures/$name').readAsStringSync();
}

Works great!

Valentin Seehausen
  • 665
  • 1
  • 8
  • 10
0

Further clarification to Danilo's answer,

  1. Put the file in test folder

enter image description here

  1. Use 'Directory.current.path' as follows

    import 'dart:io';
    
        test('submit pdf in happy path', () async {
    
        final path = '${Directory.current.path}/test/dummy.pdf';
    
    
    
         // rest of the test test code
        });
    
Heshan Sandeepa
  • 3,388
  • 2
  • 35
  • 45
-3

You can use DefaultAssetBundle,

final response = DefaultAssetBundle.of(context).loadString('assets/file_name.json');

Vinoth Kumar
  • 12,637
  • 5
  • 32
  • 38