How to mock jQuery with Jasmine

What I want to do: We are writing several tests for an existing JavaScript code base that uses jQuery heavily. For tests, we don’t want to have actual HTML elements (HTML fixtures). We would prefer it if we had a jQuery mock object that does nothing related to HTML.

My starting point: The most promising approach I have found here:

http://eclipsesource.com/blogs/2014/03/27/mocks-in-jasmine-tests/

This creates a helper method that creates a layout by looking at the functions of the object and creating a spy for each function:

window.mock = function (constr, name) { var keys = []; for (var key in constr.prototype) keys.push( key ); return keys.length > 0 ? jasmine.createSpyObj( name || "mock", keys ) : {}; }; 

Then, if I understand him correctly, he uses this like this (adapted example from his blog post):

 var el = mock($); el('.some-not-existing-class').css('background', 'red'); expect(el.css).toHaveBeenCalledWith('background', 'red'); 

However, this does not work, since el is an object , not a function .

My approach to solve this problem: I reorganized its mock function to account for the fact that constr is function :

 mock (constr, name) { var keys = []; for (var key in constr.prototype) keys.push(key); var result = keys.length > 0 ? jasmine.createSpyObj(name || "mock", keys) : {}; // make sure that if constr is a function (like in the case of jQuery), the mock is too if (typeof constr === 'function') { var result2 = result; result = jasmine.createSpy(name || 'mock-fn'); for (var key in result2) result[key] = result2[key]; } return result; } 

However, the second line of the test throws a Cannot read property css of undefined error:

 var el = mock($); el('.some-not-existing-class').css('background', 'red'); expect(el.css).toHaveBeenCalledWith('background', 'red'); 

Other ideas: I also tried combining the spy object in jQuery, but that didn't help either.

Any ideas? I hope we are not the only ones to do this without HTML lights.

+6
source share
2 answers

Found. When my version of the mock function is configured to return a jQuery object when the jQuery function is called, the test works:

 mock (constr, name) { var keys = []; for (var key in constr.prototype) keys.push(key); var result = keys.length > 0 ? jasmine.createSpyObj(name || "mock", keys) : {}; // make sure that if constr is a function (like in the case of jQuery), the mock is too if (typeof constr === 'function') { var result2 = result; result = jasmine.createSpy(name || 'mock-fn'); result.and.returnValue(result); for (var key in result2) result[key] = result2[key]; } return result; } 
0
source

You can use sinon.js stubs instead of rewinding your own helper methods.

 stub = sinon.stub(jQuery.fn, 'css'); // invoke code which calls the stubbed function expect(stub.calledWith({ 'background': 'red' })).toBe(true); stub.restore(); 
0
source

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


All Articles