简体   繁体   English

如何测试在 flutter 中使用 flutter 安全存储的 class

[英]How to test class that is using flutter secure storage in flutter

I am using "flutter_secure_storage" package in my flutter app to store token for REST API.我在我的 flutter 应用程序中使用“flutter_secure_storage”package 来存储 REST ZDB974238714CA3ACEDE408AZF 的令牌。 My Authentication class is given below:我的身份验证 class 如下所示:

import 'dart:convert';

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http;
import 'package:tutor_finder_frontend/constants/api_path.dart' as APIConstants;

class Auth {
  final _storage = FlutterSecureStorage();
  var headers = {'Content-Type': 'application/json'};

  Future<bool> isLoggedIn() async {
    final isLoggedIn = await _storage.containsKey(key: 'token');
    return isLoggedIn;
  }

  logOut() async {
    await _storage.delete(key: 'token');
  }

  Future<bool> createAccount(String email, String password) async {
    var body = jsonEncode({'email': email, 'password': password});
    var response = await http.post(Uri.parse(APIConstants.CREATE_USER_URL),
        headers: headers, body: body);

    if (response.statusCode == 201) {
      var jsonResponse = jsonDecode(response.body);
      var token = jsonResponse['token'];
      await _storage.write(key: 'token', value: token);
      return true;
    }
    return false;
  }

  Future<bool> logIn(String email, String password) async {
    var body = jsonEncode({'username': email, 'password': password});
    var response = await http.post(Uri.parse(APIConstants.LOGIN_USER_URL),
        headers: headers, body: body);

    if (response.statusCode == 200) {
      var jsonResponse = jsonDecode(response.body);
      var token = jsonResponse['token'];
      await _storage.write(key: 'token', value: token);
      return true;
    }
    return false;
  }
}

I want to test this class.我想测试这个 class。 I know about Mock and mockito package in flutter.我知道 flutter 中的 Mock 和 mockito package。 But I can't figure out how to create mock for FlutterSecureStorage class.但我不知道如何为 FlutterSecureStorage class 创建模拟。

For example, how would I call "logIn" function to store the token and then call "isLoggedIn" function to check if the token is there.例如,我如何调用“logIn”function 来存储令牌,然后调用“isLoggedIn”function 来检查令牌是否存在。 Is this even possible?这甚至可能吗? I know this may not be the usual use of Unit test.我知道这可能不是单元测试的常用用法。 Should I even do this kind of test?我什至应该做这种测试吗?

The key part is to inject the dependency to secure storage into Auth instead of declaring it as a class variable.关键部分是将安全存储的依赖注入到 Auth 中,而不是将其声明为 class 变量。 Otherwise you cannot mock it.否则你不能嘲笑它。

I would solve it further by creating an interface through which I use secure storage, and pass the interface as a variable to Auth.我将通过创建一个使用安全存储的接口来进一步解决它,并将接口作为变量传递给 Auth。 That way it is easy to mock (and also replace) that plug-in if needed.这样,如果需要,很容易模拟(也可以替换)该插件。 Abstracting away the plug-in specific dependency can often be very good.抽象掉插件特定的依赖关系通常是非常好的。

It's a good thing to test your login method.测试您的登录方法是一件好事。 But remember that you should unit test YOUR code and not make sure that SecureStorage is doing its bit correctly.但请记住,您应该对您的代码进行单元测试,而不是确保 SecureStorage 正确地完成了它的工作。 That responsibility is on the unit test of SecureStorage write method.该责任在于 SecureStorage 写入方法的单元测试。 Your unit test should make sure that secure storage's write method (or rather the interface saveToken method) is called once.您的单元测试应该确保安全存储的 write 方法(或者更确切地说是接口 saveToken 方法)被调用一次。

So something like this:所以是这样的:

class Auth {
  Auth(this._storage);
  final IStorage _storage;
  ...
}

abstract class IStorage {
  Future<void> saveToken(String token);
}

class MyStorage implements IStorage {
  MyStorage(this._storage);
  final FlutterSecureStorage _storage;

  @override
  Future<void> saveToken(String token) => _storage.write(key: 'token', value: token);
}

This way your Auth class is not directly dependant on FlutterSecureStorage, you can easily mock IStorage and make sure that all is OK in Auth.这样您的 Auth class 不直接依赖于 FlutterSecureStorage,您可以轻松地模拟 IStorage 并确保在 Auth 中一切正常。

Your test can then do something like this:然后您的测试可以执行以下操作:

class MockStorage extends Mock implements IStorage {}
final mockStorage = MockStorage();
final auth = Auth(mockStorage);
...
verify(() => mockStorage.saveToken()).called(1);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM