Mock4JS is a really useful unit testing helper library that allows you to create mocks of your JavaScript classes. What it doesn’t presently support is mocking of objects that you can’t create an instance of yourself using new Class()
or of objects that are dynamically created and have functions appended to them.
What do I mean by not being able to “create an instance of yourself using new Class()
“?
MyClassDefinition = function() { }; MyClassDefintion.prototype.myFunction = function() { // do some stuff }; MyClassDefinition = new MyClassDefinition();
Here we lose the ability to do new MyClassDefinition();
What do I mean by “objects that are dynamically created”?
// create an object using the object literal notation var oObj = {}; // dynamically append a function oObj.myFunction = function() { // do some stuff };
Code written in both these ways make it more difficult to create a mock using Mock4JS because it expects a function reference to be passed to the mock method call.
A way around this is to dynamically create a definition from the object. This is done using the following piece of code:
function createMockDefinition(oObject) { var oMockedDefinition = new Function(); for( var x in oObject ) { // Only add functions to the dynamically created prototype if( typeof oObject[ x ] == "function" ) { oMockedDefinition.prototype[x] = function(){}; } } return oMockedDefinition; };
With the above code we have now created a class definition that we can pass to the Mock4JS mock()
function.
function myTest() { var oObjectIWantToTest = {}; oObjectIWantToTest.functionIWantToTest = function(){}; var oMyMockDefinition = createMockDefinition( oObjectIWantToTest ); var oMyMock = mock( oMyMockDefinition ); var oMyMockProxy = oMyMock.proxy(); // setup expectations oMyMock.expects(once()).functionIWantToTest("myArgument"); // call function and execute mock method. oMyMockProxy.functionIWantToTest("myArgument"); // Finally, verify the expected mock methods have been called. // If not, an exception will be thrown. Mock4JS.verifyAllMocks(); };
Neat.
Sounds like it might be worth adding this feature to mock4js itself?