Flutter:测试共享首选项

28

我正在尝试测试这个函数:

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

我发现我可以使用以下方式填充共享首选项:

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

但是我不明白如何使用,特别是在我的情况下。

4个回答

59

你可以使用SharedPreferences.setMockInitialValues来进行测试。

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

当我尝试测试shared_preferences时,我一直收到错误提示。这是因为我正在运行flutter test而不是使用设备进行测试吗? - Luke Pighetti
不,你应该能够在Flutter测试中使用它。你遇到了什么样的错误? - nonybrighto
我已经处理好了,但是我不记得问题是什么了。谢谢! - Luke Pighetti
如果我使用verify(pref.setString(any, any)).called(),就会出现错误:“在非Mockito对象上使用”。 - woprandi
是的,这不适用于mockito。mockito期望一个扩展Mock的对象,例如class MockSharedPreference extends Mock implements SharedPreferences{}。我真的不知道如何让它工作。 - nonybrighto

11

感谢nonybrighto提供有帮助的答案。

我尝试使用以下代码在共享首选项中设置初始值时遇到了问题:

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

看起来 shared_preferences 插件希望使用的键具有前缀 flutter.,因此如果使用上述方法进行模拟,则需要将其添加到您自己的键中。

请参见此处第20行的证据: https://github.com/flutter/plugins/blob/2ea4bc8f8b5ae652f02e3db91b4b0adbdd499357/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart


上面的链接已经失效。 - Simon Hutton
1
感谢@SimonH - 已更新包含新文件位置的链接。 - Richard Thomas
1
自动为键添加前缀:https://github.com/flutter/plugins/blob/2ea4bc8f8b5ae652f02e3db91b4b0adbdd499357/packages/shared_preferences/shared_preferences/lib/shared_preferences.dart#L192 - Hashem Aboonajmi
@HashemAboonajmi 是正确的,你的回答不适用于你链接的修订版(也不适用于最新版本)。 - Maciej

1

我不知道这是否能帮助你,但在找到这个解决方案之前,我也浪费了很多时间。

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

}

SharedPreferences.setMockInitialValues({}); 来自哪里?我得到了“未定义的名称”的错误... - Karolina Hagegård
1
测试代码 https://pub.dev/packages/shared_preferences - Tokiniaina Eddy Andriamiandris
好的,谢谢。请在您的答案中包含该信息,以便它是完整且可运行的! - Karolina Hagegård

1
在主函数中添加这个TestWidgetsFlutterBinding.ensureInitialized();,对我来说解决了问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接