Mocking jQuery for basic usage testing

I find it very difficult to figure out how to set up an object that allows me to test my jQuery calls. I don't need to make fun of any Async calls or anything else, just basic usage. So let me outline my function that I want to test (truncated for simplicity):

listGamesCallback : function(data) { var gameList = $("#gameList select"); gameList.empty(); $.each(data, function() { var newOption = $('<option>', {value : this.gameId }); newOption.text(string); newOption.data("isJoinable", isJoinable); // Add it to the list gameList.append(newOption); }); } 

I need to make fun of jQuery here to unit test this method, but I cannot figure out how to do this in javascript. Even without jsMockito, I donโ€™t know how to create an object with properties that jQuery has in this situation. Any help with this would be appreciated.

I use jsTestDriver, jsHamcrest, jsMockito and jQuery. However, a generic approach to creating an $ object that has these properties would also be awesome. Thanks!

For those who asked, this is what I came up with, which seemed to be curious. But I do not 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 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"))) .thenReturn(mockedGamelist); when(mockContruct).call(anything(), hasItems(containsString("<option>"), both(object()).and(hasMember("value")))) .thenReturn(mockedOption); headerFunctions.listGamesCallback([ { gameId : 1, isWhitesTurn : false, isGameOver : false, whiteUserName : "foobar", blackUserName : "barfoo" } ]); JsMockito.verify(mockedGamelist).empty(); JsMockito.verify(mockedGamelist).append(mockedOption); $ = saved$; 
+6
source share
4 answers

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

 TestCase("HeaderTest", { testListGamesCallback : function () { var saved$ = $; $ = $.prototype.construct = jQuery.extend(spy(jQuery), jQuery); var mockGameList = mock(jQuery); when($)(containsString("#gameList")).thenReturn(mockGameList); headerFunctions.listGamesCallback([ { gameId : 1, isWhitesTurn : false, isGameOver : false, whiteUserName : "foobar", blackUserName : "barfoo" } ]); verify(mockGameList).empty(); verify(mockGameList).append(object()); $ = saved$; } }); 

The caveat to this solution is that mocking anything other than the constructor is a bit complicated. You will need to install each individual function that you want to make fun of, and then program the behavior. So:

  $.each = mockFunction(); when($.each)(...matchers...).thenReturn(...); 

But it still lets you check what you need.

+1
source

As an addition to the alpine answer, you can create DOM elements without adding them to the page. Make your JS functions the appropriate elements as parameters:

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

and test them like this:

 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 everything you need, you need to say that you can pass a DOM element that was never added to the page, and then examine that DOM element with jQuery to find out if it was right.

+1
source

Not sure I understand what you mean, but if you want to create โ€œdataโ€ for an example, this is a method that I know:

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

but - if you want to create a list of options, then you will need several corrections: 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") .empty(); $.each(data, function(i,d) { var newOption = $('<option>', {value : d.gameId }) .text(d.name) .data("isJoinable", d.isJoinable); // Add it to the list gameList.append(newOption); }) }; listGamesCallback(data); 
0
source

Mocking jQuery is not something that is mocked. You should only mock your employee . jQuery provides you with some utilities - it is not a co-author and therefore should not be mocked.

What you are collaborating with is the DOM or an 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 am not mocking the DOM, I am using the real DOM and I am sure that I am ripping off everything that I created between the tests, and this seems to work very well.

0
source

Source: https://habr.com/ru/post/909570/


All Articles