27

I'm trying to test this function:

 void store(String x, String y) async {
    Map<String, dynamic> map = {
      'x': x,
      'y': y,
    };
    var jsonString = json.encode(map);
    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString('fileName', jsonString);
  }

I saw that I can populate the shared preferences with

const MethodChannel('plugins.flutter.io/shared_preferences')
  .setMockMethodCallHandler((MethodCall methodCall) async {
    if (methodCall.method == 'getAll') {
      return <String, dynamic>{}; // set initial values here if desired
    }
    return null;
  });

But I didn't understand how to use, expecially in my case.

Little Monkey
  • 5,395
  • 14
  • 45
  • 83

3 Answers3

57

You can use SharedPreferences.setMockInitialValues for your test

test('Can Create Preferences', () async{

    SharedPreferences.setMockInitialValues({}); //set values here
    SharedPreferences pref = await SharedPreferences.getInstance();
    bool working = false;
    String name = 'john';
    pref.setBool('working', working);
    pref.setString('name', name);


    expect(pref.getBool('working'), false);
    expect(pref.getString('name'), 'john');
  });
nonybrighto
  • 8,752
  • 5
  • 41
  • 55
  • I keep getting errors when trying to test `shared_preferences`. Is it because I am running `flutter test` and not using a device to test? – Luke Pighetti Dec 20 '18 at 21:05
  • No. You should be able to use it in flutter test. What kind of error are you getting? – nonybrighto Dec 20 '18 at 21:10
  • I got it handled, I can't remember what the issue was though. Thank you! – Luke Pighetti Dec 21 '18 at 02:38
  • I have an error : "Used on a non-mockito object" if I use `verify(pref.setString(any, any)).called()` – woprandi Jun 16 '19 at 09:12
  • Yeah. It won't work with mockito. mockito expects an object that extends Mock like `class MockSharedPreference extends Mock implements SharedPreferences{}`. I don't really know how to make this work. – nonybrighto Jun 16 '19 at 09:50
11

Thanks to nonybrighto for the helpful answer.

I ran into trouble trying to set initial values in shared preferences using:

SharedPreferences.setMockInitialValues({
  "key": "value"
});

It appears that the shared_preferences plugin expects keys to have the prefix flutter.. This therefore needs adding to your own keys if mocking using the above method.

See line 20 here for evidence of this: https://github.com/flutter/plugins/blob/2ea4bc8f8b5ae652f02e3db91b4b0adbdd499357/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart

Richard Thomas
  • 141
  • 1
  • 7
1

I don't know if that helps you but I also lost a lot of time before finding this solution

LocalDataSourceImp.test.dart

void main(){
  SharedPreferences? preference;
  LocalDataSourceImp? localStorage ;

setUp(() async{
  preference =  await SharedPreferences.getInstance();
  localStorage = LocalDataSourceImp(preference!);
  SharedPreferences.setMockInitialValues({});
});

final token = TokenModel(data: "babakoto");

test("cache Token ", ()async{
  localStorage!.cacheToken(token);
  final result = preference!.getString(TOKEN);
  expect(result, json.encode(token.toJson()));
});
}

LocalDataSourceImp.dart

class LocalDataSourceImp implements LocalDataSource{

  SharedPreferences pref ;

  LocalDataSourceImp(this.pref);


  @override
  Future<void> cacheToken(TokenModel token)async {
    await pref.setString(TOKEN,json.encode(token));
  }

}