Take the 2-minute tour ×

I'm having a very hard time understanding how to setup an object that allows me to test my jQuery calls. I don't need to mock any Async calls or anything, just basic use. So let me set out my function that I want to test (truncated for simplicity):

listGamesCallback : function(data) {
     var gameList = $("#gameList select");


     $.each(data, function() {
          var newOption = $('<option>', {value : this.gameId });
          newOption.data("isJoinable", isJoinable);

          // Add it to the list


I need to mock the jQuery here to unit test this method, but I'm unable to figure out how to do this in javascript. Even without jsMockito, I don't know how to create an object with the properties that jQuery has in this situation. Any help with this would be appreciated.

I am using jsTestDriver, jsHamcrest, jsMockito and jQuery. However a generalized approach to create a $ object that has these properties would be awesome as well. Thank you!

For those that asked, here is what I came up with that seemed to kinda work..but I don't understand why.

var saved$ = $;

var mockContruct = mockFunction();
var mockedGamelist = mock(jQuery);
var mockedOption = mock(jQuery);

mocked$ = (function() {
    var test = function(name) {
        var args = jQuery.makeArray(arguments);
        return mockContruct.call(test, args);

    $.extend(test, $);

    // This is what confuses me.  This worked, but it's wierd
    // It allows me to use the regular jQuery functions like
    // $.each, while returning mocked objects when selectors are used.
    test.prototype.constructor = test;

    return test;

$ = mocked$;    

when(mockContruct).call(anything(), hasItem(containsString("#gameList")))

when(mockContruct).call(anything(), hasItems(containsString("<option>"), both(object()).and(hasMember("value"))))

headerFunctions.listGamesCallback([ {
    gameId : 1,
    isWhitesTurn : false,
    isGameOver : false,
    whiteUserName : "foobar",
    blackUserName : "barfoo"
} ]);


$ = saved$;
share|improve this question
It would be useful if you provided your test code as well. :) –  alpian Feb 29 '12 at 12:50
Ok, sorry for the late reply, but I've been reassigned so this got lower priority. I've got a convoluted way to run the test that I editted into the question. It is not written very well because I don't quite understand how jQuery does what it does. –  CrazyBS Mar 10 '12 at 4:03
The test you've written doesn't really prove anything other than your code executes. It can also pollute other tests with problems if it fails because you won't restore $ if it fails. I think you're still missing the point of these tests: you should be writing a test for the behaviour you're expecting from your code, not the details of how it does it. You should try to write a test that just focuses on proving that gameList having X options with whatever values in them once your function has run. –  alpian Mar 11 '12 at 22:40

4 Answers 4

Mocking jQuery is not what mocking is for. You should only ever be mocking your object's collaborators. jQuery is providing you with some utilities - it's not a collaborator and hence should not be mocked.

What you are collaborating with here is the DOM, or some intermediate object between your code and the DOM. data is a value object and can simply be created in your test as Avi suggests.

In my JS tests, i don't mock the DOM, i use the real DOM and am sure to tear down anything i created between tests and this seems to work pretty well.

share|improve this answer
I agree on my over testing in this situation. However, my thinking was that since I want my test as isolated as possible, I don't want jQuery to actually do anything, I just need to verify that it was used. This does however require that jQuery always be used to pass the test. So you have a point. –  CrazyBS Mar 10 '12 at 4:15
Can I mock the DOM?! –  CrazyBS Mar 10 '12 at 4:27
Well of course you can, but in your case i would actually just, in your test, add a REAL select with id gameList to the REAL DOM, and then run your function, and then after it's run prove (say with CSS selectors) that the DOM looks the way it should - then clean up after yourself by removing that select. Forget about trying to mock out jQuery - it's a utility - and you shouldn't need to do that :). –  alpian Mar 11 '12 at 22:43
So when you want to test a call to jQuery.ajax you should set up a fake server? I don't think there is anything wrong with mocking jQuery - what you are saying is equivalent to "no need to mock your DAL implementation, just create a test database". This is integration testing, not unit testing –  Steve Greatrex Jun 13 '12 at 7:58
jQuery is an API with massive set of tools. Some of those tools are utilities, and some are services. Obviously you would mock Ajax calls in unit tests. The OP was asking about mocking utility functions within jQuery, which is a completely different problem. –  alpian Jun 14 '12 at 18:54

No sure if i understand what you mean but if you want to create 'data' for you example , this is the method i know:

    var data = [ { id : 1 , name : 'foo' } , { id : 2, name : 'bar' ] ​

but - if you wanted to create a list of options, than you code needs a couple of fixes: see http://jsfiddle.net/7MMap/

var data = [ { gameId : 1 , name : 'foo' ,isJoinable:true} , { gameId : 2, name : 'bar' ,isJoinable:false}] 

    listGamesCallback = function(data) {
     var gameList = $("#gameList select")

     $.each(data, function(i,d) {
          var newOption = $('<option>', {value : d.gameId })
           .data("isJoinable", d.isJoinable);

          // Add it to the list

share|improve this answer
Actually, the jQuery.each() function allows you to access the value directly with 'this'. And all those .text().data() complicates the mocking and IMHO it makes it less readable. But that's just opinion. Thank you for your well formatted answer. I'm still looking to mock jQuery however. –  CrazyBS Mar 10 '12 at 4:17
up vote 0 down vote accepted

Ok, here what I came up with that does the job with minimal setup. The .extend is completely necessary here so that the jQuery object is setup correctly. This allows you to mock the constructor to return mocked jQuery objects that you can use to run your tests on. As a spy, jQuery will work as expected in all situations except when you want it to do something else. Here it is:

TestCase("HeaderTest", {
    testListGamesCallback : function () {
       var saved$ = $;

       $ = $.prototype.construct = jQuery.extend(spy(jQuery), jQuery);

       var mockGameList = mock(jQuery);

       headerFunctions.listGamesCallback([ {
          gameId : 1,
          isWhitesTurn : false,
          isGameOver : false,
          whiteUserName : "foobar",
          blackUserName : "barfoo"
       } ]);


       $ = saved$;

The caveat to this solution is that mocking anything other than the constructor is a bit tricky. You will have to set each individual function that you want to mock, then program the behavior. So:

 $.each = mockFunction();

But it still allows for testing what you need to.

share|improve this answer

As an extension to alpian's answer, you can create DOM elements without having to add them to the page. Make your JS functions take the relevant elements as parameters:

listGamesCallback : function(data, gameListSelectElem) {
    var gameList = $(gameListSelectElem);

and test them like so:

var fakeSelect = $('<select>'),
    data = ...;

listGamesCallback(data, fakeSelect[0]);

equal(fakeSelect.find('option').length, 1, 'must have exactly 1 option');

The last line of code above is for qUnit. Take whatever you need, the point is to say you can pass a DOM element that was never added to the page and afterwards investigate that DOM element using jQuery to find whether it was manipulated right.

share|improve this answer

Your Answer


