JavaScript -recommended testable pattern
I read about 2 JavaScript testable patterns, but I am not sure how they differ and which one should I use.
Pattern 1:
function class () {
this.propertyA = null;
this.methodA = function() {
alert('');
}
}
var object = new class();
object.methodA();
Pattern 2:
var object = (function() {
var propertyA = null;
return {
methodA: function() {
alert('');
}
}
}());
var object = new class();开发者_StackOverflow
object.methodA();
What are the differences? Which one should I use for unit testing with jQuery's QUnit? Please note that jQuery plugins are not an option for my requirements (not UI testing, business logic only). Thank you.
QUnit doesn't really care one way or the other. It's basically a wrapper that provides pretty output for assertions.
As for the difference between the two patterns, Pattern 1 (as you have implemented it) has all-public properties. You can do private properties, though:
function class () {
var propertyA = null;
this.methodA = function() {
alert('');
}
}
var object = new class();
object.methodA();
Pattern 2 won't actually work. You're just providing a result object wrapped in a closure, so you can't really call new
on it. You would need to do it like this:
var class = (function() {
var propertyA = null;
return function () {
return {
methodA: function() {
alert('');
}
};
}
}());
var object = new class();
object.methodA();
The whole point of the new
keyword is that it calls the object's constructor with a new variable bound to this
. If you don't have a constructor, you're just creating a singleton.
For practical purposes, here's what's happening:
- In Pattern 1, a new
propertyA
is created for each instance of class. - In Pattern 2 (as you implemented it), you're creating a singleton object.
- In Pattern 2 (as I implemented it), a single
propertyA
is shared among all instances (like static members in C++).
This is because in Pattern 1 you're creating a straightforward constructor function, which creates a new closure around the public methods for each invocation of new
. Whereas in Pattern 2, you're creating a single closure around the constructor and declaring variables outside of the constructor's scope.
The difference between these patterns is that the second pattern "hides" the internal properties -- once you have your object, you can't get to propertyA, you can only call methodA (which will itself have access to propertyA). So pattern 2 is better from an object-oriented encapsulation standpoint.
In terms of testing it shouldn't really matter, because you should be testing based on your "public" API -- the methods you call in your test should be the methods a user of your object would call -- and the two patterns should be identical. But I can imagine a scenario where, just for a test, you might need to set propertyA from the "outside". That would probably indicate a design problem. But if you can't redesign to prevent such a scenario, then you would need to use pattern 1.
精彩评论