使用Dart模拟HTTP响应

时间:2014-06-14 21:35:54

标签: mocking dart dart-unittest dart-mock

我一直在研究新的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,所以我总是得到错误:

  

顶级未捕获错误:类&#39;字符串&#39;没有实例方法   &#39;然后&#39;

我完全理解为什么我会收到此错误,但不知道如何绕过它。

任何帮助表示感谢。

4 个答案:

答案 0 :(得分:8)

http软件包已经为您testing library添加了MockClient

答案 1 :(得分:1)

尝试

.alwaysReturn(new Future.value(message401));

答案 2 :(得分: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。与diohttp软件包一起使用。

答案 3 :(得分:-1)

您可以从pub.dev中获取的http软件包中包含的tests for MockClient的一个最小示例

添加http package to your pubspec.yaml file ...

dependencies:
  http: ^0.12.2

在单元测试飞镖文件中...

import 'dart:convert';

import 'package:http/http.dart';
import 'package:http/testing.dart';
import 'package:test/test.dart';

void main() {

  test('handles a request', () async {
    var client = MockClient((request) async {
      return Response(json.encode(request.bodyFields), 200, request: request);
    }
    );

    var response = await client.post('http://example.com/foo', body: {'field1': 'value1'});

    expect(response.body, contains('value1'));
  });
}