简体   繁体   English

单元测试(Flutter 中的 MultipartRequest)

[英]Unit Test (MultipartRequest in Flutter)

This is a method I was trying to write a test for.这是我试图为其编写测试的一种方法。 I just want to write a very simple test that would just verify that send() was invoked.我只想编写一个非常简单的测试来验证send()是否被调用。 But the main trouble maker is the instance MultipartRequest .但主要的麻烦制造者是实例MultipartRequest As you can see, I am directly using the MultipartRequest instance, not as a dependency.如您所见,我直接使用MultipartRequest实例,而不是作为依赖项。 So, I don't think I am supposed to stub it.所以,我不认为我应该把它存根。 I can easily stub for getCachedToken() method as an instance of TokenValueLocalDataSource was passed in as a dependency.我可以轻松地为getCachedToken()方法存根,因为TokenValueLocalDataSource的实例作为依赖项传入。 What do you think I should do to get my desired test result?你认为我应该怎么做才能得到我想要的测试结果?

Future<Unit> addPost({
    File? imageFile,
    String? bodyText,
  }) async {
    if (imageFile != null || bodyText != null) {
      final tokenModel = await tokenValueLocalDataSource.getCachedToken();
      final stringUrl = EnvValues.addPostUrl;

      final request = http.MultipartRequest(
        'POST',
        Uri.parse(stringUrl),
      )..headers.addAll(
          {
            'Authorization': 'Token ${tokenModel.token}',
          },
        );

      if (bodyText != null) {
        request.fields['body'] = bodyText;
      }
      if (imageFile != null) {
        request.files.add(
          await http.MultipartFile.fromPath('image', imageFile.path),
        );
      }
      final response = await request.send(); // This needs to verified.
      if (response.statusCode == 200) {
        return unit;
      } else {
        throw ServerException();
      }
    } else {
      throw InvalidRequestException(
        "Both imageFile and bodyText can't be null",
      );
    }
  }

Assuming you are using the http package, here is my answer:假设您使用的是http package,这是我的答案:

Since the method itself instantiates the MultipartRequest and calls a method from it, it makes the code difficult/impossible to test.由于方法本身实例化了MultipartRequest并从中调用方法,因此它使代码难以/不可能测试。 So it is easier to use the Client class.因此使用Client class 更容易。 That is an abstract class that does the same thing and can be mocked.那是一个抽象的 class 做同样的事情并且可以被模拟。 You can see the below example after a few refactoring:经过几次重构,您可以看到以下示例:

class ApiClass {
  final http.Client _client;

  const ApiClass(this._client);

  Future<Unit> addPost({File? imageFile, String? bodyText}) async {
    if (imageFile != null || bodyText != null) {
      final tokenModel = await tokenValueLocalDataSource.getCachedToken();
      final stringUrl = EnvValues.addPostUrl;

      final request = http.MultipartRequest(
        'POST',
        Uri.parse(stringUrl),
      )..headers.addAll(
          {
            'Authorization': 'Token ${tokenModel.token}',
          },
        );

      if (bodyText != null) {
        request.fields['body'] = bodyText;
      }
      if (imageFile != null) {
        request.files.add(
          await http.MultipartFile.fromPath('image', imageFile.path),
        );
      }
      final response = await _client.send(request);
      if (response.statusCode == 200) {
        return unit;
      } else {
        throw ServerException();
      }
    } else {
      throw InvalidRequestException(
        "Both imageFile and bodyText can't be null",
      );
    }
  }
}

And the test will be something like this:测试将是这样的:

void main() {
  group('ApiClass', () {
    late ApiClass apiClass;
    late http.Client client;

    setUp(() {
      client = _MockClient();
      apiClass = ApiClass(client);
      registerFallbackValue(_FakeMultipartRequest());
    });

    test('your test description', () async {
      final response = _MockStreamedResponse();
      when(() => response.statusCode).thenReturn(200);
      when(
        () => client.send(any(
            that: isA<http.MultipartRequest>()
                .having((p0) => p0.files.length, 'has all files', 1))),
      ).thenAnswer((_) async => response);

      final result = await apiClass.addPost(bodyText: 'some text');
      expect(result, equals(unit));
    });
  });
}

class _MockStreamedResponse extends Mock implements StreamedResponse {}

class _FakeMultipartRequest extends Fake implements MultipartRequest {}

class _MockClient extends Mock implements Client {}

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

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