HttpClient和单元测试

3

我对Dart、单元测试和异步编程都很陌生,StackOverflow也一样。我试图使用shelf_route构建一个RESTful服务器,并使用HttpClient进行测试。

我的测试可以运行,但无法自动终止进程。我尝试过网上找到的几种方法,但没有成功。有人能帮帮我吗?以下是我的代码:

import 'dart:io';
import 'package:unittest/unittest.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:toner_track/handlers.dart';
import 'package:toner_track/config.dart';

void main() {
  var server;

  group('Server tests', () {
    var server;

    setUp(() {
      var handler = const shelf.Pipeline().addHandler(router);
      io.serve(handler, HOST, PORT).then((s) {
          server = s;
      });
    });

    tearDown(() {
      server.close();
    });

    test('Invalid URL returns 404', () {
      new HttpClient().getUrl(Uri.parse('http://$HOST:$PORT'))
        .then((HttpClientRequest request) => request.close())
        .then(expectAsync((HttpClientResponse response) {
          expect(response.statusCode, equals(404));
        }));
    });

    test('GET /printers returns 200', () {
      new HttpClient().getUrl(Uri.parse('http://$HOST:$PORT$rootPrintersPath'))
      .then((HttpClientRequest request) => request.close())
      .then(expectAsync((HttpClientResponse response) {
        expect(response.statusCode, equals(200));
      }));
    });

    test('POST /printers returns 201', () {
      new HttpClient().postUrl(Uri.parse('http://$HOST:$PORT$rootPrintersPath'))
        .then((HttpClientRequest request) {
          request.write('{"foo": 42}');
          return request.close();
        })
        .then(expectAsync((HttpClientResponse response) {
          expect(response.statusCode, equals(201));
        }));
    });
  });
}

更新:决定放弃HttpClient,转而使用http包。更容易处理,我的测试现在能够自动终止。显然,在第一次尝试中我没有正确处理某些东西。以下是现在代码的样子:

import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:unittest/unittest.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as io;
import 'package:toner_track/handlers.dart';
import 'package:toner_track/config.dart';

void main() {
  group('Server tests', () {
    var server;

    setUp(() {
      var handler = const shelf.Pipeline().addHandler(router);
      return io.serve(handler, HOST, PORT).then((s) {
        server = s;
      });
    });

    tearDown(() {
      server.close();
    });

    test('Invalid URL returns 404', () {
      http.get('http://$HOST:$PORT').then(expectAsync((response) {
        expect(response.statusCode, equals(404));
      }));
    });

    test('GET /printers returns 200', () {
      http.get('http://$HOST:$PORT$rootPrintersPath').then(expectAsync((response) {
        expect(response.statusCode, equals(200));
      }));
    });

    test('POST /printers returns 201', () {
      http.post('http://$HOST:$PORT$rootPrintersPath', body: {"foo": "42"}).then(expectAsync((response) {
          expect(response.statusCode, equals(201));
      }));
    });
  });
}

执行是否到达并执行了 expect 行?你有收到任何输出吗? - Günter Zöchbauer
@GünterZöchbauer 是的,expect语句会被评估,这是重要的。但是即使所有测试运行(并通过),程序仍将继续运行。我必须手动终止进程。 - mgoodness
@GünterZöchbauer 您最终通过这里间接提供了帮助。 - mgoodness
很高兴能够帮助。感谢您发布您的解决方案。 - Günter Zöchbauer
2个回答

3

看起来这似乎不是导致你问题的原因,但如果你在 setUp 中启动异步操作,你应该返回 Future。

return io.serve(handler, HOST, PORT).then((s) {
      server = s;

单元测试框架在开始运行测试之前等待未来的返回。

我认为测试也应该这样做。据我所记,有一个开放的错误,对于测试本身来说,当启动异步操作时,返回Future应该足够了,但这在setUp中没有像预期的那样工作。这是一段时间以前的事情,所以我认为现在已经修复了。

test('Invalid URL returns 404', () {
  return new HttpClient().getUrl(Uri.parse('http://$HOST:$PORT'))
    .then((HttpClientRequest request) => request.close())
    .then(expectAsync((HttpClientResponse response) {
      expect(response.statusCode, equals(404));
    }));
});

如果这个方法不起作用

test('POST / ...


test('Invalid URL returns 404', () {
  var cb = new expectAsync((){});

  new HttpClient().getUrl(Uri.parse('http://$HOST:$PORT'))
    .then((HttpClientRequest request) => request.close())
    .then(expectAsync((HttpClientResponse response) {
      expect(response.statusCode, equals(404));
      cb(); // <== to notify the unit test framework that the async operation is finished
    }));
});

谢谢你关于setUp的提示。不幸的是,其他建议都没有解决我的无休止的测试问题。 - mgoodness
我刚刚看到你的测试中已经有了expectAsync,但是你使用的方式和我略有不同。 - Günter Zöchbauer

0
在主函数的开头添加以下内容: useGoogle3VMConfiguration();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接