/* * Copyright 2004 ThoughtWorks, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ // A simple mock library for Javascript // // Original code by Aslak Hellesoy and Ji Wang Mock = function() { this.expectedInvocations = {}; this.expectedArgs = {}; this.returnValues = {}; this.attrs = []; this.expectedProperties = {}; this.expects = function() { functionName = arguments[0]; this.expectedArgs[functionName] = []; for(i = 1; i < arguments.length; i++) { this.expectedArgs[functionName][i-1] = arguments[i]; } javascriptCode = "this." + functionName + " = function() {\n" + " // mark this function as \"executed\"\n" + " this.expectedInvocations[\"" + functionName + "\"] = true;\n" + " assertEquals(\"" + functionName + ": Wrong number of arguments.\", " + this.expectedArgs[functionName].length + ", arguments.length);\n" + " for(i = 0; i < arguments.length; i++) {\n" + " assertEquals(this.expectedArgs[\"" + functionName + "\"][i], arguments[i]);\n" + " };\n" + " var returnValue = this.returnValues[\"" + functionName + "\"];\n" + " if (returnValue && returnValue.isMockError) { throw returnValue };\n" + " return returnValue;\n" + "}"; eval(javascriptCode); // initially mark this function as "not yet executed" this.expectedInvocations[functionName] = false; this.attrs[this.attrs.length] = "dummy"; return new Returner(this, functionName); }; this.expectsProperty = function() { var propertyName = arguments[0]; if(arguments.length == 2) { expectedPropertyValue = arguments[1]; this.expectedProperties[propertyName] = expectedPropertyValue; this.attrs[this.attrs.length] = "dummy"; } else { return new PropertySetter(this, propertyName); } }; this.verify = function() { // loop over all expected invocations and see if they were called for(var functionName in this.expectedInvocations) { var wasCalled = this.expectedInvocations[functionName]; if(!wasCalled) { fail("Expected function not called:" + functionName); } } var currentAttrs = []; var currentAttrCount = 0; // verify that all expected properties are set // for(var attr in this) { // currentAttrs[currentAttrCount] = attr; // currentAttrCount++; // } // if(this.attrs.length < currentAttrCount) { // unexpectedAttr = currentAttrs[this.attrs.length] // fail("Unexpected property was set: " + unexpectedAttr + "=" + eval("this." + unexpectedAttr)) // } // verify that all expected properties are set with the right value // for(var attr in this.expectedProperties) { // if(this.expectedProperties[attr] != eval("this." + attr)) { // fail("Expected property was not set: " + attr + "=" + this.expectedProperties[attr]) // } // } }; var attrCount = 0; for(var attr in this) { this.attrs[attrCount] = attr; attrCount++; } }; Returner = function(mock, functionName) { this.mock = mock; this.functionName = functionName; }; Returner.prototype.returns = function(returnValue) { this.mock.returnValues[this.functionName] = returnValue; }; Returner.prototype.andThrows = function(message) { var error = new Error(message); error.isMockError = true; this.mock.returnValues[this.functionName] = error; }; PropertySetter = function(mock, propertyName) { this.mock = mock; this.propertyName = propertyName; }; PropertySetter.prototype.returns = function(returnValue) { var ref = new Object(); ref.value = returnValue; eval("this.mock." + this.propertyName + "=ref.value"); };