Wednesday, July 17, 2013

Mock HttpRequests for Testing Dart Servers

I have not done much server-side testing in Dart yet. Tonight seems like as good a time as any to kick the tires.

Unlike client-side testing in Dart, there are a number of solid testing options available to me. The most obvious is to actually run the server and verify that the responses returned are what I expect. The other option is to convert the server.dart file into a Dart library so that the individual functions and classes can be probed directly. I will try the latter tonight since it just seems more fun.

To import a library for test, the thing being imported needs to be a… library. To convert test_server.dart into a library, I need only add the library statement to the top of the file:

In the main() entry point, I have written my first test that verifies that I can get a 404 response back from the non-existent request handling code. Actually, there is no real test there—I am just wondering if I can create a new HttpRequest object.

Bah! I am on the fence, but I do not think that I like this. It bothers me a little that I cannot directly create this object. It bothers me more that I can create an HttpRequest instance on the client side.

In this case, I am getting the HttpRequest class from the dart:io library. When I code Dart in the browser, a different HttpRequest class comes from the dart:html library. HttpRequest from dart:io is meant to handle HTTP requests in a server environment. HttpRequest from dart:html is a replacement for the venerable XMLHttpRequest object for performing so-called AJAX operations.

I cannot create instances of HttpRequest from dart:io—only a server's listen stream can do that. It is still possible to make HTTP requests from the command-line in Dart—the HttpClient class does that. Naturally, it does not have an HttpRequest object for me to use, preferring to expose them in futures.

Basically, I am stuck. I cannot create an HttpRequest object for my server test. But I can create something the quacks like an HttpRequest duck. Rather than building a fake class manually, I am going to give the mock library a go. I may be trying one too many new things at this point, but what the hey?

The mock library is already included in the unittest library, so there is no need to update my pubspec.yaml. It already depends on unittest:

name: plumbur_kruk
#...
dependencies:
unittest: any

Since I already have unittest there is also no need to install with Dart Pub.

I should be good to create a mock instance of HttpRequest. I update my test to import the mock library, then I create a MockHttpRequest as implementing HttpRequest, and finally create an instance of this mock class:

In addition to creating the mock request object, I give it some behavior. I tell it that, when it sees calls to the response getter, it should always return my mock HTTP response object. This syntax feels a little awkward, but it is fairly readable.

Next, I call the noResponseFound() method in my actual test server with the mock request object:

PlumburKruk.notFoundResponse(req);

Last, I need to check the mock request object's “logs” to see how many times the statusCode setter was told to assign a 404 value:

I am pretty excited to finally have put the mock library in Dart to some good use—all the more so because the resultant test is pretty solid. It would still make some sense to contrast this approach with a real HTTP client and server, which I will likely tackle tomorrow.