5

私は新しい API ラッパーに取り組んでおり、単体テストを実行するたびに API を呼び出したくありません。hereで説明されているように、私はそれを嘲笑しています。

私は最初、私がそれを嘲笑している方法に何か問題があると思っていましたが、問題は他の場所にあるようです.

私が達成しようとしていることは非常に簡単です。単体テストの実行時に、統合している外部 API から情報を取得するために外出したかのように、値を返したいと考えています。

オプションのパラメーターとして http.Client を使用してクラスを初期化するため、単体テストを実行するときにそれを渡すことができます。

SampleClass(String arg1, String arg2, [http.Client httpClient = null]) {
    this._arg1 = arg1;
    this._arg2 = arg2;
    _httpClient = (httpClient == null) ? http.Request : httpClient;
}

Future apiRequest(String resource, [Map<String, String> body]) {
    var url = buildBaseUrl(resource).toString();
    var request = new http.Request('POST', Uri.parse(url));
    request.bodyFields = body;
    return this._httpClient.send(request).then((response) => response.stream.bytesToString().then((value) => value.toString()));
}

単体テストでは、次のモック クラスを作成しました。

class HttpClientMock extends Mock implements http.Client {
  noSuchMethod(i) => super.noSuchMethod(i);
}

class HttpResponseMock extends Mock implements http.Response {
    noSuchMethod(i) => super.noSuchMethod(i);
}

そして、応答を確認するための単体テストでは、次のことを行っています。

test("Send SMS errors with wrong account", () {
    var mockHttpClient = new HttpClientMock()
                             ..when(callsTo('send')).alwaysReturn(message401);
    var sample = new SampleClass(_arg1, _arg2, mockHttpClient);
    future = sample.apiRequest(...parameters here...).then((value) => value.toString());
    expect(future.then((value) => JSON.decode(value)), completion(equals(JSON.decode(message401))));
});

ご覧のとおり、 send を呼び出すとmessage401、単なるJSON文字列であるが返されるようにしようとしています。

は文字列であるため、これは発生していません。message401私のコードはそれを Future として使用しようとするため、常にエラーが発生します。

トップレベルのキャッチされないエラー: クラス 'String' にはインスタンス メソッド 'then' がありません。

このエラーが発生する理由は完全に理解していますが、回避する方法がわかりません。

どんな助けでも感謝します。

4

4 に答える 4

12

このhttpパッケージには、MockClientが既に実装されているテスト ライブラリが含まれています。

于 2014-06-14T22:15:28.483 に答える
1

そのためのnockパッケージがあります。

import 'package:test/test.dart';
import 'package:http/http.dart' as http;
import 'package:nock/nock.dart';

void main() {
  setUpAll(() {
    nock.init();
  });

  setUp(() {
    nock.cleanAll();
  });

  test("example", () async {
    final interceptor = nock("http://localhost/api").get("/users")
      ..reply(
        200,
        "result",
      );

    final response = await http.get("http://localhost/api/users");

    expect(interceptor.isDone, true);
    expect(response.statusCode, 200);
    expect(response.body, "result");
  });
}

HttpOverrides を使用するため、MockClient を注入する必要はありません。dioとパッケージの両方で動作しhttpます。

于 2020-10-09T14:03:49.860 に答える