How to unit test a jQuery selector?
Just a quick question... I currently have the following jQuery code with a selector in it.
var ID = "idControl"
function doesTreeViewExist()
{
if($('#' + ID).length == 0)
{
return false;
}
else
{
return true;
}
}
I was wondering how do I write the test to test the selector using QUnit? More specifically, I'm having trouble coming up with the syntax/code.
EDIT:
Ok, suppose now I want to mock the se开发者_Go百科lector call instead because I cannot get access to the actual website. I'm using JsTestDriver as my testing tool, which means I cannot touch the browser the tests are running in (else the test runs will stop). What about in such situation? How can I possibly test the code?
Thanks.
The function you post, can be heavily simplified:
var ID = "idControl";
function doesTreeViewExist() {
return !!$('#' + ID).length;
}
Using the !!
construct (double bitwise NOT), to convert the length
property to Boolean, it will return false
only when length is zero.
Speaking about qUnit, you can easily setup a simple test like this:
test("Your selector test", function() {
ok($('#idControl').length > 0, "idControl exists");
// or simply
ok($('#idControl').length, "idControl exists");
});
The ok
function does a boolean assertion, equivalent to JUnit's assertTrue.
I test selectors manually, then pass them to code that uses them. I can then unit test the code that uses them. If you want to just test a selector, you need access to the HTML it affects. Your test could include HTML to target, something like:
test("selector works", function() {
var html = $('<input type="select"><option value=0/></input');
var result = $('option', html);
ok(result.count() == 1);
});
But I don't do that... I put my selectors at the edge of the code so I can get to them quickly and step through them under the debugger. I'll have a simple class whose properties are those selectors. Then I'll mock/stub that simple class, so I can write code for everything dependent on those selectors. The reason I don't test my selectors is because the HTML they target is generated by ASP.NET code, and hard to get to from a javascript test. But I can wrap them in a Humble Object ("http://xunitpatterns.com/Humble Object.html") then test code that depends on that humble object. Here's a simple wrapper class that I can replace with test doubles:
var createSelectWidget = function(rootSelector)
{
return {
userText : $('span', rootSelector),
inputList : $('option', rootSelector),
};
}
Whatever dependency injection pattern you use, you can then stub it like below. Suppose my widget has a select input to read the value of, and a span I want to write some results to:
var createSelectWidgetStub = function()
{
return {
userText : { text = function() {}},
inputList : { val = function() {}},
};
}
I can then pass around this stub in tests where I want to isolate the dependency but don't care about interactions with that dependency. When I want to verify interactions with the dependency, I can mock it with JSMock. Suppose I want to verify interactions with the input list, I would prepare a stub with the one element mock'd:
var selectMock = createSelectWidgetStub();
selectMock.inputList = mc.createMock(selectMock.inputList);
I used Jack and successfully mocked the jquery call and returned a custom length and expected result.
Something like:
jack (function() {
jack.expect("$").exactly("1").withArguments("#" + ID).returnValue( {length:0} );
doesTreeViewExist()
assertEquals(false, result);
});
I have also managed to supply a DOM structure to satisfy the jquery call, as I'm using one of JsTestDriver's built-in function HtmlDoc. Something like:
/*:DOC += <span id="idControl"></span> */
or simply create a DOM sturcture without the specified id to get the false statement.
HTH.
精彩评论