Reputation: 546
New to Dart, unit testing, and asynchronous programming in general. And StackOverflow, for that matter. Trying to build a RESTful server around shelf_route and test it using HttpClient.
My tests work, but they don't exit on their own. Instead, I have to terminate the process manually. I've tried several approaches I found online, but no luck. Can anyone give me a hand? Here's what I'm working with:
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));
}));
});
});
}
UPDATE: Decided to abandon HttpClient in favor of the http
package. Much easier to work with, and my tests now terminate on their own. Clearly I wasn't handling something correctly in my first go-around. Here's what the above code looks like now:
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));
}));
});
});
}
Upvotes: 3
Views: 432
Reputation: 1011
Add the following at the start of the main function: useGoogle3VMConfiguration();
Upvotes: 0
Reputation: 657278
It doesn't look like this is the cause for your issue, but if you start async operation in setUp
you should return the Future.
return io.serve(handler, HOST, PORT).then((s) {
server = s;
The unit test framework waits for the future to return before it starts running the tests.
I think the tests should do the same. As far as I remember there was an open bug that for the tests itself it should be sufficient to return the Future when an async operation was started but that it didn't work here like in setUp
. This was a while ago, so I assume this is fixed.
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));
}));
});
If this doesn't work
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
}));
});
Upvotes: 3