├── LICENSE ├── README.md ├── lib ├── nodemock.js └── npm-debug.log ├── package.json └── test ├── index.html └── nodemock.js /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2014 Arunoda Susiripala 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Node Mock - Simple Yet Powerful Mocking Framework for NodeJs 2 | ============================================================ 3 | 4 | NodeMock is a very simple to use mocking framework which can be used to 5 | mock functions in JavaScript objects. 6 | NodeMock creates mock methods in less code with more expressive manner. 7 | 8 | I have passed the reins of maintenance for this project to 9 | [Curtis Schlak](http://curtis.schlak.com). You can find new changes to it 10 | over at [nodemock](https://github.com/realistschuckle/nodemock). 11 | -------------------------------------------------------------------------------- /lib/nodemock.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | The MIT License 4 | 5 | Copyright (c) 2011 Arunoda Susiripala 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | */ 26 | 27 | function NodeMock(methodName) { 28 | 29 | var self = this; 30 | var currentMockFunction = null; 31 | 32 | var entries = {}; 33 | 34 | var mockFunction = function(method, avoid) { 35 | 36 | function getValidEntry(args) { 37 | 38 | //Iterate over to find a entry matching argument list 39 | for(var index in entries[method]) { 40 | var entry = entries[method][index]; 41 | 42 | if(entry.executed == false && deepObjectCheck(entry.args, args)) { 43 | //increasing executed numbers for that entry 44 | entry.executed = true; 45 | return entry; 46 | } 47 | } 48 | 49 | return false; 50 | } 51 | 52 | return function() { 53 | //check for argument length 54 | var entry; 55 | 56 | if(!self[method]) { 57 | throw new Error("Mock function '" + method + "()' is not defined"); 58 | 59 | } else if(!(entry = getValidEntry(arguments))) { 60 | 61 | var expected = ""; 62 | var alreadyExecuted = false; 63 | for(var key in entries[method]) { 64 | var entry = entries[method][key]; 65 | if(entry.executed == false) { 66 | expected += "\n\t" + getParamString(entry.args); 67 | } else if(deepObjectCheck(entry.args, arguments)) { 68 | alreadyExecuted = true; 69 | } 70 | } 71 | 72 | expected += "\n"; 73 | 74 | if(alreadyExecuted) { 75 | throw new Error('method: ' + method + getParamString(arguments) + ' already executed'); 76 | } else { 77 | throw new Error( 78 | "Arguments content passed: " + getParamString(arguments) + 79 | " is not tally with expected: " + expected + " in method: '" + method + "()'"); 80 | } 81 | 82 | } else if(entry.shouldFail) { 83 | throw new Error("You should not call: '" + method+ "()' with params: " + getParamString(arguments) + " on this object"); 84 | } 85 | 86 | //calling the callback 87 | if(entry.callbackIndex != null) { 88 | var func = arguments[entry.callbackIndex]; 89 | entry.callback = func; 90 | 91 | if(entry.callbackArgs) { 92 | if(typeof(func) == "function") { 93 | func.apply(this, entry.callbackArgs || []); 94 | } else { 95 | throw new Error("Expected callback is not defined as callback"); 96 | } 97 | } 98 | } 99 | 100 | return entry.returns; 101 | }; 102 | }; 103 | 104 | this.takes = function() { 105 | var entry = getCurrentEntry(); 106 | entry.args = arguments; 107 | return this; 108 | }; 109 | 110 | this.times = function(expected) { 111 | var entry = getCurrentEntry(); 112 | for(var lc = 0; lc < expected - 1; lc++) { 113 | addEntry(cloneEntry(entry)); 114 | } 115 | return this; 116 | }; 117 | 118 | this.returns = function(value) { 119 | var entry = getCurrentEntry(); 120 | entry.returns = value; 121 | return this; 122 | }; 123 | 124 | this.ctrl = function(index, obj) { 125 | var entry = getCurrentEntry(); 126 | entry.callbackIndex = index; 127 | entry.callbackArgs = false; 128 | 129 | obj.trigger = function() { 130 | if(entry.callback) { 131 | entry.callback.apply(this, arguments); 132 | } else { 133 | throw new Error("There is no callback to control"); 134 | } 135 | }; 136 | 137 | return this; 138 | }; 139 | 140 | this.calls = function() { 141 | 142 | if(typeof(arguments[0]) == "number") { 143 | var entry = entries[currentMockFunction][entries[currentMockFunction].length - 1]; 144 | 145 | entry.callbackIndex = arguments[0]; 146 | if(arguments[1] && (arguments[1] instanceof Array)) { 147 | entry.callbackArgs = arguments[1]; 148 | } 149 | 150 | return this; 151 | } else if(arguments[0] instanceof Object) { 152 | 153 | } else { 154 | throw new Error("First arg of the calls() should be the index of the callback"); 155 | } 156 | }; 157 | 158 | this.assert = function() { 159 | 160 | var success = true; 161 | for(var method in entries) { 162 | var entriesForMethod = entries[method]; 163 | entriesForMethod.forEach(function(entry) { 164 | if(!entry.shouldFail && entry.executed == false) { 165 | success = false; 166 | console.error( 167 | "method call for: '" + method + "()' with params: " + getParamString(entry.args) + " was not executed!\n" 168 | ); 169 | } 170 | }); 171 | } 172 | 173 | return success; 174 | }; 175 | 176 | this.assertThrows = function() { 177 | var success = this.assert(); 178 | if(!success) { 179 | throw new Error('Nodemock rules breaked!'); 180 | } 181 | }; 182 | 183 | //Assign the mocking function 184 | this.mock = function(method) { 185 | 186 | if(method) { 187 | //let the current mocking method be this 188 | currentMockFunction = method; 189 | 190 | if(!this[method]) { 191 | 192 | entries[currentMockFunction] = []; 193 | //assign the mock method 194 | this[method] = mockFunction(method); 195 | } 196 | 197 | addEntry({ 198 | args: [], 199 | callback: null, 200 | callbackIndex: null, 201 | callbackArgs: [], 202 | returns: undefined, 203 | executed: false, // whether the mock entry executed or not 204 | shouldFail: false 205 | }); 206 | } 207 | 208 | return this; 209 | }; 210 | 211 | /** 212 | * After this call when someone calls on this this object is'll 213 | * throw an exception 214 | */ 215 | this.fail = function() { 216 | var entry = getCurrentEntry(); 217 | entry.shouldFail = true; 218 | return this; 219 | }; 220 | 221 | /** 222 | cleanup all the rules and the mock methods 223 | */ 224 | this.reset = function() { 225 | entries = {}; 226 | currentMockFunction = null; 227 | 228 | var bypass = { 229 | 'takes': true, 230 | 'times': true, 231 | 'returns': true, 232 | 'ctrl': true, 233 | 'calls': true, 234 | 'assert': true, 235 | 'assertThrows': true, 236 | 'mock': true, 237 | 'fail': true, 238 | 'reset': true, 239 | 'ignore': true 240 | }; 241 | 242 | for(var key in this) { 243 | if(!bypass[key]) { 244 | delete this[key]; 245 | } 246 | } 247 | }; 248 | 249 | //ignore the mock 250 | this.ignore = function(method) { 251 | 252 | this[method] = function() {}; 253 | }; 254 | 255 | //method for cloning entry 256 | function cloneEntry(entry) { 257 | var clone = {}; 258 | for(var key in entry) { 259 | clone[key] = entry[key]; 260 | } 261 | return clone; 262 | } 263 | 264 | function getCurrentEntry() { 265 | return entries[currentMockFunction][entries[currentMockFunction].length - 1]; 266 | } 267 | 268 | function addEntry(entry) { 269 | entries[currentMockFunction].push(entry); 270 | } 271 | 272 | function getParamString(params) { 273 | 274 | var paramString = "("; 275 | for(var index in params) { 276 | var param = params[index]; 277 | if(param instanceof Function) { 278 | paramString += "function() {}, "; 279 | } else if(param instanceof RegExp) { 280 | paramString += param.toString() + ", "; 281 | } else { 282 | paramString += JSON.stringify(param) + ", "; 283 | } 284 | } 285 | 286 | if(params[0]) { 287 | return paramString = paramString.substring(0, paramString.length -2) + ")"; 288 | } else { 289 | return '()'; 290 | } 291 | }; 292 | 293 | function deepObjectCheck(expected, actual) { 294 | 295 | if(expected && actual && (expected.length != actual.length)) return false; 296 | 297 | for(var key in expected) { 298 | 299 | var actualType = typeof(actual[key]); 300 | var expectedType = typeof(expected[key]); 301 | 302 | if(actualType != expectedType) return false; 303 | if(actualType == "function") { 304 | continue; 305 | } else if(actualType == "object") { 306 | if(!deepObjectCheck(expected[key] ,actual[key])) return false; 307 | } else { 308 | if(actual[key] != expected[key]) return false; 309 | } 310 | } 311 | 312 | return true; 313 | }; 314 | 315 | //initialize the mocking 316 | this.mock(methodName); 317 | 318 | } 319 | 320 | //Supporting NodeJS CommonJS module system 321 | if(typeof(exports) != "undefined") { 322 | 323 | exports.mock = function(methodName) { 324 | return new NodeMock(methodName); 325 | }; 326 | 327 | exports.fail = function() { 328 | return new NodeMock(); 329 | }; 330 | 331 | exports.ignore = function(method) { 332 | var nm = new NodeMock(); 333 | nm.ignore(method); 334 | return nm; 335 | }; 336 | } 337 | -------------------------------------------------------------------------------- /lib/npm-debug.log: -------------------------------------------------------------------------------- 1 | info it worked if it ends with ok 2 | verbose cli [ 'node', '/usr/local/bin/npm', 'install', '-g' ] 3 | info using npm@1.0.10 4 | info using node@v0.4.5 5 | verbose config file /home/arunoda/.npmrc 6 | verbose config file /usr/local/etc/npmrc 7 | verbose into /usr/local/lib [ '.' ] 8 | verbose cache add [ '.', null ] 9 | ERR! couldn't read package.json in . 10 | ERR! Error: ENOENT, No such file or directory 'package.json' 11 | ERR! Report this *entire* log at: 12 | ERR! 13 | ERR! or email it to: 14 | ERR! 15 | ERR! 16 | ERR! System Linux 2.6.35-22-generic 17 | ERR! command "node" "/usr/local/bin/npm" "install" "-g" 18 | verbose exit [ 2, true ] 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodemock", 3 | "version": "0.2.17", 4 | "directories": { 5 | "lib": "./lib" 6 | }, 7 | "main": "./lib/nodemock", 8 | "description": "Simple Yet Powerful Mocking Framework for NodeJs", 9 | "author": "Arunoda Susiripala ", 10 | "homepage": "https://github.com/arunoda/nodemock", 11 | "licenses": [ 12 | { 13 | "type": "The MIT License", 14 | "url": "http://www.opensource.org/licenses/mit-license.php" 15 | } 16 | ], 17 | 18 | "repository" : 19 | { 20 | "type" : "git", 21 | "url" : "git@github.com:arunoda/nodemock.git" 22 | }, 23 | 24 | "tags" : ["mock", "unit", "testing", "nodemock"] 25 | } 26 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /test/nodemock.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License 4 | 5 | Copyright (c) 2011 Arunoda Susiripala 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | */ 26 | 27 | //NodeMock argument check 28 | var nm = require("../lib/nodemock"); 29 | 30 | exports.testArgumentSimple = function(test) { 31 | 32 | var mock = nm.mock("foo").takes(10, "Hello", true, [1, 4, 5], {"a": "aa", "b": "bb"}); 33 | test.doesNotThrow(function(){ 34 | mock.foo(10, "Hello", true, [1, 4, 5], {"a": "aa", "b": "bb"}); 35 | }); 36 | 37 | test.throws(function() { 38 | mock.foo(11, "Hello", true, [1, 4, 5], {"a": "aa", "b": "bb"}); 39 | }); 40 | 41 | test.throws(function() { 42 | mock.foo(10, "Hello1", true, [1, 4, 5], {"a": "aa", "b": "bb"}); 43 | }); 44 | 45 | test.throws(function() { 46 | mock.foo(10, "Hello", false, [1, 4, 8], {"a": "aa", "b": "bb"}); 47 | }); 48 | 49 | test.throws(function() { 50 | mock.foo(10, "Hello", true, [1, 4, 5], {"a": "aa", "b": "gh"}); 51 | }); 52 | 53 | test.throws(function() { 54 | mock.foo(10, "Hello", true, [1, 4, 5], {"a": "aa", "c": "gh"}); 55 | }); 56 | 57 | test.done(); 58 | }; 59 | 60 | exports.testWithJustReturn = function(test) { 61 | 62 | var mock = nm.mock("foo").returns(false); 63 | test.ok(!mock.foo()); 64 | 65 | test.done(); 66 | }; 67 | 68 | exports.testArgumentsDeep = function(test) { 69 | 70 | var mock = nm.mock("foo").takes([10, 20, {a: "aa", b: [10, 20]}]); 71 | 72 | test.doesNotThrow(function() { 73 | mock.foo([10, 20, {a: "aa", b: [10, 20]}]); 74 | }); 75 | 76 | test.throws(function() { 77 | mock.foo([10, 21, {a: "aa", b: [10, 20]}]); 78 | }); 79 | 80 | test.throws(function() { 81 | mock.foo([10, 20, {a: "aa3", b: [10, 20]}]); 82 | }); 83 | 84 | test.throws(function() { 85 | mock.foo([10, 20, {a: "aa", b: [10, 20, 30]}]); 86 | }); 87 | 88 | test.done(); 89 | }; 90 | 91 | //Nodemock Return Check 92 | 93 | exports.testReturn = function(test) { 94 | 95 | var mock = nm.mock("foo").returns(10); 96 | test.equal(mock.foo(), 10); 97 | 98 | test.done(); 99 | }; 100 | 101 | //Nodemock Callback Tests 102 | 103 | exports.testCallbackCorrect = function(test) { 104 | 105 | var mock = nm.mock("foo").takes(10, function(){}).calls(1, [10, 20]); 106 | test.expect(2); 107 | mock.foo(10, function(a, b) { 108 | test.equals(a, 10); 109 | test.equals(b, 20); 110 | }); 111 | 112 | test.done(); 113 | }; 114 | 115 | exports.testCallbackNoArgsDefined = function(test) { 116 | 117 | var mock = nm.mock("foo").calls(1, [10, 20]); 118 | 119 | test.throws(function() { 120 | mock.foo(10, function(a, b) { 121 | test.equals(a, 10); 122 | test.equals(b, 20); 123 | }); 124 | }); 125 | 126 | test.done(); 127 | }; 128 | 129 | exports.testCallbackSurplusArgs = function(test) { 130 | 131 | var mock = nm.mock("foo").takes(10, function(){}).calls(1, [10, 20, 30, 40]); 132 | test.expect(2); 133 | mock.foo(10, function(a, b) { 134 | test.equals(a, 10); 135 | test.equals(b, 20); 136 | }); 137 | 138 | test.done(); 139 | }; 140 | 141 | exports.testCallbackLessArgs = function(test) { 142 | 143 | var mock = nm.mock("foo").takes(10, function(){}).calls(1, [10]); 144 | test.expect(2); 145 | mock.foo(10, function(a, b) { 146 | test.equals(a, 10); 147 | test.equals(b, undefined); 148 | }); 149 | 150 | test.done(); 151 | }; 152 | 153 | exports.testCallbackNoArgs = function(test) { 154 | 155 | var mock = nm.mock("foo").takes(10, function(){}).calls(1, []); 156 | test.expect(2); 157 | mock.foo(10, function(a, b) { 158 | test.equals(a, undefined); 159 | test.equals(b, undefined); 160 | }); 161 | 162 | test.done(); 163 | }; 164 | 165 | exports.testCallbackNullArgs = function(test) { 166 | 167 | var mock = nm.mock("foo").takes(10, function(){}).calls(1, null); 168 | test.expect(2); 169 | mock.foo(10, function(a, b) { 170 | test.equals(a, undefined); 171 | test.equals(b, undefined); 172 | }); 173 | 174 | test.done(); 175 | }; 176 | 177 | exports.testCallbackWithoutArgs = function(test) { 178 | 179 | var mock = nm.mock("foo").takes(10, function(){}).calls(1); 180 | test.expect(2); 181 | mock.foo(10, function(a, b) { 182 | test.equals(a, undefined); 183 | test.equals(b, undefined); 184 | }); 185 | 186 | test.done(); 187 | }; 188 | 189 | exports.testMockAgain = function(test) { 190 | 191 | var mock = nm.mock("foo").takes(10, 20).returns(30); 192 | test.doesNotThrow(function() { 193 | test.equal(mock.foo(10, 20), 30); 194 | }); 195 | 196 | mock.mock("bar").takes(10).returns(40); 197 | test.doesNotThrow(function() { 198 | test.equal(mock.bar(10), 40); 199 | }); 200 | 201 | test.throws(function() { 202 | test.equal(mock.foo(10, 20), 30); 203 | }); 204 | test.done(); 205 | }; 206 | 207 | exports.testFailNoAnyMockMethod = function(test) { 208 | 209 | var mock = nm.fail(); 210 | test.throws(function() { 211 | mock.foo(); 212 | }); 213 | test.done(); 214 | }; 215 | 216 | exports.testFailOneMockMethod = function(test) { 217 | 218 | var mock = nm.mock("foo").fail(); 219 | mock.mock("bar").takes(10, 20); 220 | test.throws(function() { 221 | mock.foo(); 222 | }); 223 | 224 | test.doesNotThrow(function() { 225 | mock.bar(10, 20); 226 | }); 227 | test.done(); 228 | }; 229 | 230 | exports.testMultipleEntriesForOneMethod = function(test) { 231 | var mock = nm.mock("foo").takes(10, 20).returns(30); 232 | mock.mock("foo").takes(10, 30).returns(40); 233 | 234 | test.doesNotThrow(function() { 235 | test.ok(mock.foo(10, 20) == 30); 236 | test.ok(mock.foo(10, 30) == 40); 237 | }); 238 | 239 | test.throws(function() { 240 | mock.foo(10); 241 | mock.foo(10, 20); 242 | mock.bar(10, 30); 243 | }); 244 | 245 | test.done(); 246 | }; 247 | 248 | exports.testAssertFailsSameMethod = function(test) { 249 | 250 | var mock = nm.mock("foo").takes(10, 20).returns(30); 251 | mock.mock("foo").takes(10, 30).returns(40); 252 | 253 | mock.foo(10,20); 254 | test.ok(!mock.assert()); 255 | test.done(); 256 | }; 257 | 258 | exports.testAssertFailsManyMethod = function(test) { 259 | 260 | var mock = nm.mock("foo").takes(10, 20).returns(30); 261 | mock.mock("bar").takes(10, 30).returns(40); 262 | 263 | mock.foo(10,20); 264 | test.ok(!mock.assert()); 265 | test.done(); 266 | }; 267 | 268 | exports.testAssertOK = function(test) { 269 | 270 | var mock = nm.mock("foo").takes(10, 20).returns(30); 271 | mock.mock("foo").takes(10, 30).returns(40); 272 | mock.mock("bar").returns(30); 273 | 274 | mock.foo(10,20); 275 | mock.foo(10,30); 276 | mock.bar(); 277 | test.ok(mock.assert()); 278 | test.done(); 279 | }; 280 | 281 | exports.testAssertThrowsFailed = function(test) { 282 | 283 | var mock = nm.mock("foo").takes(10, 20).returns(30); 284 | mock.mock("bar").takes(10, 30).returns(40); 285 | 286 | mock.foo(10,20); 287 | test.throws(function() { 288 | mock.assertThrows(); 289 | }); 290 | test.done(); 291 | }; 292 | 293 | exports.testAssertThrowsOK = function(test) { 294 | 295 | var mock = nm.mock("foo").takes(10, 20).returns(30); 296 | mock.mock("foo").takes(10, 30).returns(40); 297 | mock.mock("bar").returns(30); 298 | 299 | mock.foo(10,20); 300 | mock.foo(10,30); 301 | mock.bar(); 302 | test.doesNotThrow(function() { 303 | mock.assertThrows(); 304 | }); 305 | test.done(); 306 | }; 307 | 308 | exports.testTimes = function(test) { 309 | 310 | var mock = nm.mock("foo").takes(10, 20).times(2); 311 | mock.foo(10, 20); 312 | mock.foo(10, 20); 313 | test.ok(mock.assert()); 314 | 315 | mock = nm.mock("bar").takes(10).times(2); 316 | mock.bar(10); 317 | test.ok(!mock.assert()); 318 | 319 | test.done(); 320 | }; 321 | 322 | exports.testCtrl = function(test) { 323 | 324 | test.expect(2); 325 | var ctrl = {}; 326 | var mock = nm.mock("foo").takes(10, 20, function() {}).ctrl(2, ctrl); 327 | 328 | mock.foo(10, 20, function(bb) { 329 | test.ok(bb = 20); 330 | }); 331 | 332 | ctrl.trigger(20); 333 | ctrl.trigger(20); 334 | 335 | test.done(); 336 | }; 337 | 338 | exports.testPartialCompareBug1 = function (test){ 339 | 340 | test.throws(function (){ 341 | var mock = nm.mock('foo').takes({hi: 1, bye: 2000},2,3) 342 | mock.foo({},2,3) //should throw because bye: 2000 is not present 343 | }) 344 | 345 | test.done() 346 | } 347 | 348 | exports.testPartialCompareBug2 = function (test){ 349 | 350 | test.throws(function (){ 351 | var mock = nm.mock('foo').takes({hi: 1, bye: 2000},2,3) 352 | mock.foo({hi: 1},2,3) //should throw because bye: 2000 is not present 353 | mock.foo({},2,3) //should throw because bye: 2000 is not present 354 | }) 355 | 356 | test.done() 357 | } 358 | 359 | exports.testPartialCompare = function (test){ 360 | 361 | test.doesNotThrow(function (){ 362 | var mock = nm.mock('foo').takes({hi: 1},2,3) 363 | mock.foo({hi: 1, bye: 2000},2,3) //should throw because bye: 2000 is not present 364 | }) 365 | 366 | test.throws(function (){ 367 | var mock = nm.mock('foo').takes({hi: 1},2,3) 368 | mock.foo({},2,3) //should throw because bye: 2000 is not present 369 | }) 370 | 371 | test.done() 372 | 373 | }; 374 | 375 | exports.multiReturn = function(test) { 376 | 377 | var mock = nm.mock("foo").returns(1); 378 | mock.mock("foo").returns(2); 379 | mock.mock("foo").takes(1).returns(42); 380 | 381 | test.equal(mock.foo(), 1, "good first return"); 382 | test.equal(mock.foo(), 2, "good second return"); 383 | test.equal(mock.foo(1), 42, "still match on arguments"); 384 | test.ok(mock.assert(), 'bad invoked mocks'); 385 | 386 | test.throws(function() { 387 | test.equal(mock.foo(), 2, "re-uses second return"); 388 | }); 389 | 390 | test.done(); 391 | }; 392 | 393 | exports.testCopyFunction = function(test) { 394 | 395 | var mock = nm.mock('foo').returns(10); 396 | var foo = mock.foo; 397 | test.equal(foo(), 10); 398 | test.done(); 399 | }; 400 | 401 | exports.testReset = function(test) { 402 | 403 | var mock = nm.mock('foo').returns(100); 404 | test.equal(mock.foo(), 100); 405 | test.ok(mock.assert()); 406 | 407 | mock.reset(); 408 | test.ok(!mock.foo); 409 | 410 | mock.mock('doo').returns(300); 411 | test.equal(mock.doo(), 300); 412 | 413 | test.ok(mock.assert()); 414 | test.done(); 415 | }; 416 | 417 | exports.testIgnore = function(test) { 418 | 419 | var mock = nm.mock('foo').returns(100); 420 | test.equal(mock.foo(), 100); 421 | 422 | mock.ignore('hello'); 423 | test.ok(mock.hello); 424 | 425 | test.doesNotThrow(function() { 426 | mock.hello(); 427 | }); 428 | 429 | test.done(); 430 | 431 | }; 432 | 433 | exports.testIgnoreRootMethod = function(test) { 434 | 435 | var mock = nm.ignore('hello'); 436 | test.ok(mock.hello); 437 | 438 | test.doesNotThrow(function() { 439 | mock.hello(); 440 | }); 441 | 442 | test.done(); 443 | 444 | }; 445 | 446 | exports.testIgnoreAfterReset = function(test) { 447 | 448 | 449 | var mock = nm.mock('foo').returns(10); 450 | mock.reset(); 451 | mock.ignore('hello'); 452 | test.ok(mock.hello); 453 | 454 | test.doesNotThrow(function() { 455 | mock.hello(); 456 | }); 457 | 458 | test.done(); 459 | 460 | }; 461 | 462 | exports.testFailThrowsNoExceptionWhenNotCalled = function(test){ 463 | 464 | var mock = nm.mock('test').fail(); 465 | test.doesNotThrow(function() { 466 | // the method was not called so, no exception should be thrown 467 | mock.assertThrows(); 468 | }); 469 | test.done(); 470 | } --------------------------------------------------------------------------------