mockmatchers_test.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  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. goog.provide('goog.testing.mockmatchersTest');
  15. goog.setTestOnly('goog.testing.mockmatchersTest');
  16. goog.require('goog.dom');
  17. goog.require('goog.dom.TagName');
  18. goog.require('goog.testing.jsunit');
  19. goog.require('goog.testing.mockmatchers');
  20. goog.require('goog.testing.mockmatchers.ArgumentMatcher');
  21. // A local reference to the mockmatchers namespace.
  22. var matchers = goog.testing.mockmatchers;
  23. // Simple classes to test the InstanceOf matcher.
  24. var foo = function() {};
  25. var bar = function() {};
  26. // Simple class to test adding error messages to
  27. // MockExpectation objects
  28. function MockMock() {
  29. this.errorMessages = [];
  30. }
  31. var mockExpect = null;
  32. MockMock.prototype.addErrorMessage = function(msg) {
  33. this.errorMessages.push(msg);
  34. };
  35. MockMock.prototype.getErrorMessageCount = function() {
  36. return this.errorMessages.length;
  37. };
  38. function setUp() {
  39. mockExpect = new MockMock();
  40. }
  41. function testNoMatchName() {
  42. // A matcher that does not fill in the match name
  43. var matcher = new goog.testing.mockmatchers.ArgumentMatcher(goog.isString);
  44. // Make sure the lack of match name doesn't affect the ability
  45. // to return True/False
  46. assertTrue(matcher.matches('hello'));
  47. assertFalse(matcher.matches(123));
  48. // Make sure we handle the lack of a match name
  49. assertFalse(matcher.matches(456, mockExpect));
  50. assertEquals(1, mockExpect.errorMessages.length);
  51. assertEquals(
  52. 'Expected: missing mockmatcher description ' +
  53. 'but was: <456> (Number)',
  54. mockExpect.errorMessages[0]);
  55. }
  56. function testInstanceOf() {
  57. var matcher = new matchers.InstanceOf(foo);
  58. assertTrue(matcher.matches(new foo()));
  59. assertFalse(matcher.matches(new bar()));
  60. assertFalse(matcher.matches(new bar(), mockExpect));
  61. assertEquals(1, mockExpect.errorMessages.length);
  62. assertEquals(
  63. 'Expected: instanceOf() ' +
  64. 'but was: <[object Object]> (Object)',
  65. mockExpect.errorMessages[0]);
  66. }
  67. function testTypeOf() {
  68. var matcher = new matchers.TypeOf('number');
  69. assertTrue(matcher.matches(1));
  70. assertTrue(matcher.matches(2));
  71. assertFalse(matcher.matches('test'));
  72. assertFalse(matcher.matches(true, mockExpect));
  73. assertEquals(1, mockExpect.errorMessages.length);
  74. assertEquals(
  75. 'Expected: typeOf(number) but was: <true> (Boolean)',
  76. mockExpect.errorMessages[0]);
  77. }
  78. function testRegexpMatch() {
  79. var matcher = new matchers.RegexpMatch(/^cho[dtp]/);
  80. assertTrue(matcher.matches('chodhop'));
  81. assertTrue(matcher.matches('chopper'));
  82. assertFalse(matcher.matches('chocolate'));
  83. assertFalse(matcher.matches(null));
  84. assertFalse(matcher.matches('an anger', mockExpect));
  85. assertEquals(1, mockExpect.errorMessages.length);
  86. assertEquals(
  87. 'Expected: match(/^cho[dtp]/) but was: <an anger> (String)',
  88. mockExpect.errorMessages[0]);
  89. }
  90. function testObjectEquals() {
  91. // Test a simple match.
  92. var simpleMatcher = new matchers.ObjectEquals({name: 'Bob', age: 42});
  93. assertTrue(simpleMatcher.matches({name: 'Bob', age: 42}, mockExpect));
  94. assertEquals(0, mockExpect.getErrorMessageCount());
  95. expectObjectEqualsFailure(
  96. simpleMatcher, {name: 'Bill', age: 42},
  97. 'name: Expected <Bob> (String) but was <Bill> (String)');
  98. expectObjectEqualsFailure(
  99. simpleMatcher, {name: 'Bob', age: 21},
  100. 'age: Expected <42> (Number) but was <21> (Number)');
  101. expectObjectEqualsFailure(
  102. simpleMatcher, {name: 'Bob'},
  103. 'property age not present in actual Object');
  104. expectObjectEqualsFailure(
  105. simpleMatcher, {name: 'Bob', age: 42, country: 'USA'},
  106. 'property country not present in expected Object');
  107. // Multiple mismatches should include multiple messages.
  108. expectObjectEqualsFailure(
  109. simpleMatcher, {name: 'Jim', age: 36},
  110. 'name: Expected <Bob> (String) but was <Jim> (String)\n' +
  111. ' age: Expected <42> (Number) but was <36> (Number)');
  112. }
  113. function testComplexObjectEquals() {
  114. var complexMatcher = new matchers.ObjectEquals(
  115. {a: 'foo', b: 2, c: ['bar', 3], d: {sub1: 'baz', sub2: -1}});
  116. assertTrue(
  117. complexMatcher.matches(
  118. {a: 'foo', b: 2, c: ['bar', 3], d: {sub1: 'baz', sub2: -1}}));
  119. expectObjectEqualsFailure(
  120. complexMatcher,
  121. {a: 'foo', b: 2, c: ['bar', 3], d: {sub1: 'zap', sub2: -1}},
  122. 'sub1: Expected <baz> (String) but was <zap> (String)');
  123. expectObjectEqualsFailure(
  124. complexMatcher,
  125. {a: 'foo', b: 2, c: ['bar', 6], d: {sub1: 'baz', sub2: -1}},
  126. 'c[1]: Expected <3> (Number) but was <6> (Number)');
  127. }
  128. function testSaveArgument() {
  129. var saveMatcher = new matchers.SaveArgument();
  130. assertTrue(saveMatcher.matches(42));
  131. assertEquals(42, saveMatcher.arg);
  132. saveMatcher = new matchers.SaveArgument(goog.isString);
  133. assertTrue(saveMatcher.matches('test'));
  134. assertEquals('test', saveMatcher.arg);
  135. assertFalse(saveMatcher.matches(17));
  136. assertEquals(17, saveMatcher.arg);
  137. saveMatcher =
  138. new matchers.SaveArgument(new matchers.ObjectEquals({value: 'value'}));
  139. assertTrue(saveMatcher.matches({value: 'value'}));
  140. assertEquals('value', saveMatcher.arg.value);
  141. assertFalse(saveMatcher.matches('test'));
  142. assertEquals('test', saveMatcher.arg);
  143. }
  144. function testIsArray() {
  145. assertTrue(matchers.isArray.matches([]));
  146. assertTrue(matchers.isArray.matches(new Array()));
  147. assertFalse(matchers.isArray.matches('test'));
  148. assertFalse(matchers.isArray.matches({}, mockExpect));
  149. assertEquals(1, mockExpect.errorMessages.length);
  150. assertEquals(
  151. 'Expected: isArray but was: <[object Object]> (Object)',
  152. mockExpect.errorMessages[0]);
  153. }
  154. function testIsArrayLike() {
  155. var nodeList = (function() {
  156. var div = goog.dom.createElement(goog.dom.TagName.DIV);
  157. div.appendChild(goog.dom.createElement(goog.dom.TagName.P));
  158. div.appendChild(goog.dom.createElement(goog.dom.TagName.P));
  159. return goog.dom.getElementsByTagName(goog.dom.TagName.DIV, div);
  160. })();
  161. assertTrue(matchers.isArrayLike.matches([]));
  162. assertTrue(matchers.isArrayLike.matches(new Array()));
  163. assertTrue(matchers.isArrayLike.matches(nodeList));
  164. assertFalse(matchers.isArrayLike.matches('test'));
  165. assertFalse(matchers.isArrayLike.matches(3, mockExpect));
  166. assertEquals(1, mockExpect.errorMessages.length);
  167. assertEquals(
  168. 'Expected: isArrayLike but was: <3> (Number)',
  169. mockExpect.errorMessages[0]);
  170. }
  171. function testIsDateLike() {
  172. assertTrue(matchers.isDateLike.matches(new Date()));
  173. assertFalse(matchers.isDateLike.matches('test'));
  174. assertFalse(matchers.isDateLike.matches('test', mockExpect));
  175. assertEquals(1, mockExpect.errorMessages.length);
  176. assertEquals(
  177. 'Expected: isDateLike but was: <test> (String)',
  178. mockExpect.errorMessages[0]);
  179. }
  180. function testIsString() {
  181. assertTrue(matchers.isString.matches('a'));
  182. assertTrue(matchers.isString.matches('b'));
  183. assertFalse(matchers.isString.matches(null));
  184. assertFalse(matchers.isString.matches(null, mockExpect));
  185. assertEquals(1, mockExpect.errorMessages.length);
  186. assertEquals(
  187. 'Expected: isString but was: <null>', mockExpect.errorMessages[0]);
  188. }
  189. function testIsBoolean() {
  190. assertTrue(matchers.isBoolean.matches(true));
  191. assertTrue(matchers.isBoolean.matches(false));
  192. assertFalse(matchers.isBoolean.matches(null));
  193. assertFalse(matchers.isBoolean.matches([], mockExpect));
  194. assertEquals(1, mockExpect.errorMessages.length);
  195. assertEquals(
  196. 'Expected: isBoolean but was: <> (Array)', mockExpect.errorMessages[0]);
  197. }
  198. function testIsNumber() {
  199. assertTrue(matchers.isNumber.matches(-1));
  200. assertTrue(matchers.isNumber.matches(1));
  201. assertTrue(matchers.isNumber.matches(1.25));
  202. assertFalse(matchers.isNumber.matches(null));
  203. assertFalse(matchers.isNumber.matches('hello', mockExpect));
  204. assertEquals(1, mockExpect.errorMessages.length);
  205. assertEquals(
  206. 'Expected: isNumber but was: <hello> (String)',
  207. mockExpect.errorMessages[0]);
  208. }
  209. function testIsFunction() {
  210. assertTrue(matchers.isFunction.matches(function() {}));
  211. assertFalse(matchers.isFunction.matches('test'));
  212. assertFalse(matchers.isFunction.matches({}, mockExpect));
  213. assertEquals(1, mockExpect.errorMessages.length);
  214. assertEquals(
  215. 'Expected: isFunction but was: <[object Object]> (Object)',
  216. mockExpect.errorMessages[0]);
  217. }
  218. function testIsObject() {
  219. assertTrue(matchers.isObject.matches({}));
  220. assertTrue(matchers.isObject.matches(new Object()));
  221. assertTrue(matchers.isObject.matches(new function() {}));
  222. assertTrue(matchers.isObject.matches([]));
  223. assertTrue(matchers.isObject.matches(new Array()));
  224. assertTrue(matchers.isObject.matches(function() {}));
  225. assertFalse(matchers.isObject.matches(null));
  226. assertFalse(matchers.isObject.matches(1234, mockExpect));
  227. assertEquals(1, mockExpect.errorMessages.length);
  228. assertEquals(
  229. 'Expected: isObject but was: <1234> (Number)',
  230. mockExpect.errorMessages[0]);
  231. }
  232. function testIsNodeLike() {
  233. assertFalse(matchers.isNodeLike.matches({}));
  234. assertFalse(matchers.isNodeLike.matches(1));
  235. assertFalse(matchers.isNodeLike.matches(function() {}));
  236. assertFalse(matchers.isNodeLike.matches(false));
  237. assertTrue(matchers.isNodeLike.matches(document.body));
  238. assertTrue(matchers.isNodeLike.matches(goog.dom.getElement('someDiv')));
  239. assertFalse(matchers.isNodeLike.matches('test', mockExpect));
  240. assertEquals(1, mockExpect.errorMessages.length);
  241. assertEquals(
  242. 'Expected: isNodeLike but was: <test> (String)',
  243. mockExpect.errorMessages[0]);
  244. }
  245. function testIgnoreArgumentsMatcher() {
  246. // ignoreArgument always returns true:
  247. assertTrue(matchers.ignoreArgument.matches());
  248. assertTrue(matchers.ignoreArgument.matches(356));
  249. assertTrue(matchers.ignoreArgument.matches('str'));
  250. assertTrue(matchers.ignoreArgument.matches(['array', 123, false]));
  251. assertTrue(matchers.ignoreArgument.matches({'map': 1, key2: 'value2'}));
  252. }
  253. function testFlexibleArrayMatcher() {
  254. // Test that basic lists are verified properly.
  255. var a1 = [1, 'test'];
  256. var a2 = [1, 'test'];
  257. var a3 = [1, 'test', 'extra'];
  258. assertTrue(matchers.flexibleArrayMatcher(a1, a2));
  259. assertFalse(matchers.flexibleArrayMatcher(a1, a3));
  260. // Test that basic lists with basic class instances are verified properly.
  261. var instance = new foo();
  262. a1 = [1, 'test', instance];
  263. a2 = [1, 'test', instance];
  264. a3 = [1, 'test', new foo()];
  265. assertTrue(matchers.flexibleArrayMatcher(a1, a2));
  266. assertTrue(matchers.flexibleArrayMatcher(a1, a3));
  267. // Create an argument verifier that returns a consistent value.
  268. var verifyValue = true;
  269. var argVerifier = function() {};
  270. goog.inherits(argVerifier, matchers.ArgumentMatcher);
  271. argVerifier.prototype.matches = function(arg) { return verifyValue; };
  272. // Test that the arguments are always verified when the verifier returns
  273. // true.
  274. a1 = [1, 'test', new argVerifier()];
  275. a2 = [1, 'test', 'anything'];
  276. a3 = [1, 'test', 12345];
  277. assertTrue(matchers.flexibleArrayMatcher(a1, a2));
  278. assertTrue(matchers.flexibleArrayMatcher(a1, a3));
  279. // Now test the case when then verifier returns false.
  280. verifyValue = false;
  281. assertFalse(matchers.flexibleArrayMatcher(a1, a2));
  282. assertFalse(matchers.flexibleArrayMatcher(a1, a3));
  283. // And test we report errors back up via the opt_expectation
  284. assertFalse(matchers.flexibleArrayMatcher(a2, a3, mockExpect));
  285. assertEquals(1, mockExpect.errorMessages.length);
  286. assertEquals(
  287. 'Expected <anything> (String) but was <12345> (Number)\n' +
  288. ' Expected <anything> (String) but was <12345> (Number)',
  289. mockExpect.errorMessages[0]);
  290. // And test we report errors found via the matcher
  291. a1 = [1, goog.testing.mockmatchers.isString];
  292. a2 = [1, 'test string'];
  293. a3 = [1, null];
  294. assertTrue(matchers.flexibleArrayMatcher(a1, a2, mockExpect));
  295. assertFalse(matchers.flexibleArrayMatcher(a1, a3, mockExpect));
  296. // Old error is still there
  297. assertEquals(2, mockExpect.errorMessages.length);
  298. assertEquals(
  299. 'Expected <anything> (String) but was <12345> (Number)\n' +
  300. ' Expected <anything> (String) but was <12345> (Number)',
  301. mockExpect.errorMessages[0]);
  302. // plus the new error...
  303. assertEquals(
  304. 'Expected: isString but was: <null>', mockExpect.errorMessages[1]);
  305. }
  306. /**
  307. * Utility method for checking for an ObjectEquals match failure. Checks that
  308. * the expected error message was included in the error messages appended to
  309. * the expectation object.
  310. * @param {goog.testing.mockmatchers.ArgumentMatcher.ObjectEquals} matcher
  311. * The matcher to test against.
  312. * @param {Object} matchObject The object to compare.
  313. * @param {string=} opt_errorMsg The deep object comparison failure message
  314. * to check for.
  315. */
  316. function expectObjectEqualsFailure(matcher, matchObject, opt_errorMsg) {
  317. mockExpect.errorMessages = [];
  318. assertFalse(matcher.matches(matchObject, mockExpect));
  319. assertNotEquals(0, mockExpect.getErrorMessageCount());
  320. if (opt_errorMsg) {
  321. assertContains(opt_errorMsg, mockExpect.errorMessages[0]);
  322. }
  323. }