Monday, December 24, 2012

Cannot Stub HttpRequest in Dart

‹prev | My Chain | next›

Up today, I hope to figure out how to test HttpRequest code in Dart. I began building a test suite for the first chapter in Dart for Hipsters yesterday, but that client-side code did little more than not crash.

The remainder of the code in Chapter One builds around HttpRequest code such as:
main() {
  load_comics();
}

load_comics() {
  var list_el = document.query('#comics-list')
    , req = new HttpRequest();

  req.open('get', '/comics', true);

  req.on.load.add((res) {
    var list = JSON.parse(req.responseText);
    list_el.innerHTML = graphic_novels_template(list);
    attach_delete_handlers(list_el);
  });

  req.send();
}
I will try to test the actual functionality later. For now. I start with a simple returnsNormally test:
    test('the app returns OK', (){
      expect(Main.main, returnsNormally);
    });
Unfortunately, that results in the following failure:
[main] the app returns OK. Expected: return normally but: threw <Error: NETWORK_ERR: XMLHttpRequest Exception 101>.
This particular error results from an HttpRequest attempt from a file:// page (the HTML page that holds the tests). In the Dart console I see a JavaScripty complaint:
XMLHttpRequest cannot load file:///comics. Cross origin requests are only supported for HTTP.
Unfortunately, I think I am stuck here. There is no way to redefine a method in Dart, so I have no hope of redefining open(). I might try to redefine the HttpRequest class so that it returns a real or fake HttpRequest object depending on a static variable setting. Unfortunately, this kind of thing will not work:
class MockHttpRequest implements HttpRequest {}
class RealHttpRequest  {
  factory RealHttpRequest() => new HttpRequest();
}

class HttpRequest {
  factory HttpRequest() {
    return new RealHttpRequest();
  }
}
This turns out to be a good way to generate a stack overflow (RealHttpRequest return an instance of HttpRequest, which returns an instance of RealHttpRequest).

My real problem is that I absolutely must stick with creating an instance of HttpRequest using the form:
req = new HttpRequest();
Were this real-world code, I could use some form of dependency injection to supply an alternate HttpRequest object. I do this sort of thing in HipsterSync in the Hipster MVC library.

What I would really like is some way to intercept or stub all network connections in Dart. But this seems a ways off at this time. So I find myself stuck with this particular bit of code. I will mull this over a bit, but I may have to either leave this bit of code untested or I may have to resort to some kind of Frankenstein-like code sample assembly in the book. Neither option is particularly pleasant, but I do not see many alternatives.


Day #609

No comments:

Post a Comment