functionmock.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Copyright 2008 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Enable mocking of functions not attached to objects
  16. * whether they be global / top-level or anonymous methods / closures.
  17. *
  18. * See the unit tests for usage.
  19. *
  20. */
  21. goog.setTestOnly('goog.testing');
  22. goog.provide('goog.testing');
  23. goog.provide('goog.testing.FunctionMock');
  24. goog.provide('goog.testing.GlobalFunctionMock');
  25. goog.provide('goog.testing.MethodMock');
  26. goog.require('goog.object');
  27. goog.require('goog.testing.LooseMock');
  28. goog.require('goog.testing.Mock');
  29. goog.require('goog.testing.PropertyReplacer');
  30. goog.require('goog.testing.StrictMock');
  31. /**
  32. * Class used to mock a function. Useful for mocking closures and anonymous
  33. * callbacks etc. Creates a function object that extends goog.testing.Mock.
  34. * @param {string=} opt_functionName The optional name of the function to mock.
  35. * Set to '[anonymous mocked function]' if not passed in.
  36. * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
  37. * goog.testing.Mock.STRICT. The default is STRICT.
  38. * @return {!goog.testing.MockInterface} The mocked function.
  39. * @suppress {missingProperties} Mocks do not fit in the type system well.
  40. */
  41. goog.testing.FunctionMock = function(opt_functionName, opt_strictness) {
  42. var fn = function() {
  43. var args = Array.prototype.slice.call(arguments);
  44. args.splice(0, 0, opt_functionName || '[anonymous mocked function]');
  45. return fn.$mockMethod.apply(fn, args);
  46. };
  47. var base = opt_strictness === goog.testing.Mock.LOOSE ?
  48. goog.testing.LooseMock :
  49. goog.testing.StrictMock;
  50. goog.object.extend(fn, new base({}));
  51. return /** @type {!goog.testing.MockInterface} */ (fn);
  52. };
  53. /**
  54. * Mocks an existing function. Creates a goog.testing.FunctionMock
  55. * and registers it in the given scope with the name specified by functionName.
  56. * @param {Object} scope The scope of the method to be mocked out.
  57. * @param {string} functionName The name of the function we're going to mock.
  58. * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
  59. * goog.testing.Mock.STRICT. The default is STRICT.
  60. * @return {!goog.testing.MockInterface} The mocked method.
  61. */
  62. goog.testing.MethodMock = function(scope, functionName, opt_strictness) {
  63. if (!(functionName in scope)) {
  64. throw Error(functionName + ' is not a property of the given scope.');
  65. }
  66. var fn = goog.testing.FunctionMock(functionName, opt_strictness);
  67. fn.$propertyReplacer_ = new goog.testing.PropertyReplacer();
  68. fn.$propertyReplacer_.set(scope, functionName, fn);
  69. fn.$tearDown = goog.testing.MethodMock.$tearDown;
  70. return fn;
  71. };
  72. /**
  73. * Mocks an existing function. Creates a goog.testing.FunctionMock
  74. * and registers it according to scopeFunctionName.
  75. * @param {!goog.testing.ObjectPropertyString} scopeFunctionName Scope and
  76. * function name.
  77. * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
  78. * goog.testing.Mock.STRICT. The default is STRICT.
  79. * @return {!goog.testing.MockInterface} The mocked method.
  80. */
  81. goog.testing.MethodMock.fromObjectPropertyString = function(
  82. scopeFunctionName, opt_strictness) {
  83. return goog.testing.MethodMock(
  84. scopeFunctionName.getObject(), scopeFunctionName.getPropertyString(),
  85. opt_strictness);
  86. };
  87. /**
  88. * @private
  89. * @record @extends {goog.testing.MockInterface}
  90. */
  91. goog.testing.MethodMock.MockInternalInterface_ = function() {};
  92. /** @const {!goog.testing.PropertyReplacer} */
  93. goog.testing.MethodMock.MockInternalInterface_.prototype.$propertyReplacer_;
  94. /**
  95. * Resets the global function that we mocked back to its original state.
  96. * @this {goog.testing.MockInterface}
  97. */
  98. goog.testing.MethodMock.$tearDown = function() {
  99. /** @type {!goog.testing.MethodMock.MockInternalInterface_} */ (this)
  100. .$propertyReplacer_.reset();
  101. };
  102. /**
  103. * Mocks a global / top-level function. Creates a goog.testing.MethodMock
  104. * in the global scope with the name specified by functionName.
  105. * @param {string} functionName The name of the function we're going to mock.
  106. * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
  107. * goog.testing.Mock.STRICT. The default is STRICT.
  108. * @return {!goog.testing.MockInterface} The mocked global function.
  109. */
  110. goog.testing.GlobalFunctionMock = function(functionName, opt_strictness) {
  111. return goog.testing.MethodMock(goog.global, functionName, opt_strictness);
  112. };
  113. /**
  114. * Convenience method for creating a mock for a function.
  115. * @param {string=} opt_functionName The optional name of the function to mock
  116. * set to '[anonymous mocked function]' if not passed in.
  117. * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
  118. * goog.testing.Mock.STRICT. The default is STRICT.
  119. * @return {!goog.testing.MockInterface} The mocked function.
  120. */
  121. goog.testing.createFunctionMock = function(opt_functionName, opt_strictness) {
  122. return goog.testing.FunctionMock(opt_functionName, opt_strictness);
  123. };
  124. /**
  125. * Convenience method for creating a mock for a method.
  126. * @param {Object} scope The scope of the method to be mocked out.
  127. * @param {string} functionName The name of the function we're going to mock.
  128. * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
  129. * goog.testing.Mock.STRICT. The default is STRICT.
  130. * @return {!goog.testing.MockInterface} The mocked global function.
  131. */
  132. goog.testing.createMethodMock = function(scope, functionName, opt_strictness) {
  133. return goog.testing.MethodMock(scope, functionName, opt_strictness);
  134. };
  135. /**
  136. * Convenience method for creating a mock for a constructor. Copies class
  137. * members to the mock.
  138. *
  139. * <p>When mocking a constructor to return a mocked instance, remember to create
  140. * the instance mock before mocking the constructor. If you mock the constructor
  141. * first, then the mock framework will be unable to examine the prototype chain
  142. * when creating the mock instance.
  143. * @param {Object} scope The scope of the constructor to be mocked out.
  144. * @param {string} constructorName The name of the constructor we're going to
  145. * mock.
  146. * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
  147. * goog.testing.Mock.STRICT. The default is STRICT.
  148. * @return {!goog.testing.MockInterface} The mocked constructor.
  149. */
  150. goog.testing.createConstructorMock = function(
  151. scope, constructorName, opt_strictness) {
  152. var realConstructor = scope[constructorName];
  153. var constructorMock =
  154. goog.testing.MethodMock(scope, constructorName, opt_strictness);
  155. // Copy class members from the real constructor to the mock. Do not copy
  156. // the closure superClass_ property (see goog.inherits), the built-in
  157. // prototype property, or properties added to Function.prototype
  158. for (var property in realConstructor) {
  159. if (property != 'superClass_' && property != 'prototype' &&
  160. realConstructor.hasOwnProperty(property)) {
  161. constructorMock[property] = realConstructor[property];
  162. }
  163. }
  164. return constructorMock;
  165. };
  166. /**
  167. * Convenience method for creating a mocks for a global / top-level function.
  168. * @param {string} functionName The name of the function we're going to mock.
  169. * @param {number=} opt_strictness One of goog.testing.Mock.LOOSE or
  170. * goog.testing.Mock.STRICT. The default is STRICT.
  171. * @return {!goog.testing.MockInterface} The mocked global function.
  172. */
  173. goog.testing.createGlobalFunctionMock = function(functionName, opt_strictness) {
  174. return goog.testing.GlobalFunctionMock(functionName, opt_strictness);
  175. };