Javascript Testing – Getting in the Groove

Posted over 2 years ago on October 23, 2010

The past week has been spent continuing my journey of refactoring massive amounts of javscript that was written baked into the jQuery ready callback

Nagging Questions

While I've been pulling out behavior and encapsulating it into javascript objects, a few design questions keep popping up.  First, when I need to interact with the DOM I struggle with how to make my object aware of the page elements.  I have at least a few options:

* Inject the DOM elements into the object constructor:

function SomeClass(element1, element2) {
  this.element1 = element1;
  this.element2 = element2;
}

This solution allows me to not have to worry about adding DOM elements to a test fixture.  In my test I can just pass object literals into the ctor.  The tradeoff is that if the object depends on many elements then the constructor parameter list can get unwieldy. 

* Allow the object constructor to locate the elements:

function SomeClass() {
  this.element1 = $("input#Element1");
  this.element2 = $("input#Element2");
}

Here I can avoid the big ctor parameter list, but now I have to simulate some of my DOM elements inside the test.  The testing framework I'm using makes this very easy, but there's something troubling about duplicating the elements here.

* Pass page elements into object instance methods as needed

function SomeClass() {
  this.user_took_some_action = function(element1, element2) {
    //Do stuff
  }
}

This might appear be a happy medium between the other two solutions, but it also breaks some of the encapsulation I'm trying to achieve.  There are often times where two or more instance methods interact with the same DOM elements. 

I?ve been trying to observe my TDD patterns to see what leads me to the most testable solution, but it seems like every situation is different.  I'm torn on whether or not I care about consistency.

The next question I keep bumping into is dealing with service location.  Do I pass the dependencies into the constructor and/or instance methods, or just create them inside the instance methods?  Coupled with the above discussion, my parameter lists can start to get muddled with both DOM elements AND dependencies.  Not ideal.  Ideally I would just create dependencies as I need them inside my instance methods:

function SomeClass() {
  this.user_took_some_action = function(element1, element2) {
    var dependency = new Dependency();
    dependency.make_me_some_pie();
    //other stuff
  }
}

Since javascript is a dynamic language I thought it would be a breeze to stub out the dependency, and it is...but only after I asked the Twitters for some help:  http://gist.github.com/639861

This seems like a great way to go if you don't mind the extra work/code of stubbing using this technique.

Comments

New Comment