簡體   English   中英

單元測試(Flutter 中的 MultipartRequest)

[英]Unit Test (MultipartRequest in Flutter)

這是我試圖為其編寫測試的一種方法。 我只想編寫一個非常簡單的測試來驗證send()是否被調用。 但主要的麻煩制造者是實例MultipartRequest 如您所見,我直接使用MultipartRequest實例,而不是作為依賴項。 所以,我不認為我應該把它存根。 我可以輕松地為getCachedToken()方法存根,因為TokenValueLocalDataSource的實例作為依賴項傳入。 你認為我應該怎么做才能得到我想要的測試結果?

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

假設您使用的是http package,這是我的答案:

由於方法本身實例化了MultipartRequest並從中調用方法,因此它使代碼難以/不可能測試。 因此使用Client class 更容易。 那是一個抽象的 class 做同樣的事情並且可以被模擬。 經過幾次重構,您可以看到以下示例:

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

測試將是這樣的:

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