Yesterday I managed to get a simple Dart test server running for the purposes of unit testing
HttpRequest code. Emphasis on the word simple. All that it does is return a JSON string regardless of the request.Today, I would like to test POSTing and possibly PUTting updates. To accomplish this, I am going to need to be able to persist data in my test server. I could do this in memory, but I have a quick and dirty way to do this already. So I add dart dirty as a dependency (along with UUID for IDs) to the list of dependencies in the library I am trying to test:
name: hipster_mvc version: 0.2.6 description: Dart-based MVC framework author: Chris StromA quickhomepage: https://github.com/eee-c/hipster-mvc dependencies: unittest: any dirty: any uuid: any js: any
pub update and I have my quick and dirt noSQL database ready to go:➜ hipster-mvc git:(http-test-server) ✗ pub update Resolving dependencies......... Dependencies updated! ➜ hipster-mvc git:(http-test-server) ✗ ls packages browser dirty hipster_mvc js meta unittest uuidI would like to be able to write a test along the lines of:
test("it can POST new records", (){
_test(response) {
expect(response, {'test': 42});
}
var model = new FakeModel();
model.url = 'http://localhost:31337/widgets';
model.attributes = {'test': 42};
HipsterSync.call('create', model).then(expectAsync1(_test));
});I am creating a fake model which is attempting to persist data in Hipster MVC at the /widgets path on my test server. I expect that when I POST / create data that the server will reply back to me with the contents that I have created:{'test': 42}.I need to start building out my test server to support this, so I add the necessary
import statements along with a handler for the /widgets path:import 'dart:io';
import 'dart:json' as JSON;
import 'package:dirty/dirty.dart';
import 'package:uuid/uuid.dart';
main() {
var port = Platform.environment['PORT'] == null ?
31337 : int.parse(Platform.environment['PORT']);
HttpServer.bind('127.0.0.1', port).then((app) {
app.listen((HttpRequest req) {
if (req.uri.path.startsWith('/widgets')) {
handleWidgets(req);
return;
}
defaultResponse(req);
});
});
}To handle the /widgets, I need to determine the HTTP verb that is being used to make the request. I also need to know if the request includes an ID or not:handleWidgets(req) {
var r = new RegExp(r"/widgets/([-\w\d]+)");
var id_path = r.firstMatch(req.uri.path),
id = (id_path == null) ? null : id_path[1];
if (req.method == 'POST') return createWidget(req);
if (req.method == 'GET' && id != null) readWidget(req);
notFoundResponse(req);
}I will add more over the next few days, but that is a decent start. Now, I need to be able to create widgets in the persisted DB:createWidget(req) {
HttpResponse res = req.response;
Uuid uuid = new Uuid();
Dirty db = new Dirty('test.db');
req.toList().then((list) {
var post_data = new String.fromCharCodes(list[0]);
var widget = JSON.parse(post_data);
widget['id'] = uuid.v1();
db[widget['id']] = widget;
res.statusCode = 201;
res.headers.contentType =
new ContentType("application", "json", charset: "utf-8");
res.write(JSON.stringify(widget));
res.close();
});
}I am probably trying to do too much in there. I am reading the body of the request for the POSTed JSON data. Then I turn around and fashion a response. At the same time, I am writing to the test DB. As I said, I could probably clean that up, but it will do for now—at least as a test server.With that, I have my test passing, but I still have a problem: the test DB is sticking around:
➜ hipster-mvc git:(http-test-server) ✗ cat test/test.db
{"key":"962c9aa0-c9c0-11e2-9027-23f0a97992d8","val":{"test":42,"id":"962c9aa0-c9c0-11e2-9027-23f0a97992d8"}}I will explore teardown HTTP paths tomorrow, but for now, I manually remove this in my continuous integration script:echo "starting test server" dart test/test_server.dart & server_pid=$! echo "content_shell --dump-render-tree test/index.html" results=`content_shell --dump-render-tree test/index.html 2>&1` # ... kill $server_pid rm -f test/test.db # ...That seems a decent stopping point for tonight. Setting up the server and the “routing” was a bit more challenging that I had expected (I keep thinking that I have finally found a use for
case statements in Dart only to be proven wrong). Still, this seems promising for testing the remainder of Hipster MVC's RESTful routing methods, which I hope to finish off tomorrow.Day #804
No comments:
Post a Comment