strictmock.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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 This file defines a strict mock implementation.
  16. */
  17. goog.setTestOnly('goog.testing.StrictMock');
  18. goog.provide('goog.testing.StrictMock');
  19. goog.require('goog.array');
  20. goog.require('goog.testing.Mock');
  21. /**
  22. * This is a mock that verifies that methods are called in the order that they
  23. * are specified during the recording phase. Since it verifies order, it
  24. * follows 'fail fast' semantics. If it detects a deviation from the
  25. * expectations, it will throw an exception and not wait for verify to be
  26. * called.
  27. * @param {Object|Function} objectToMock The object that should be mocked, or
  28. * the constructor of an object to mock.
  29. * @param {boolean=} opt_mockStaticMethods An optional argument denoting that
  30. * a mock should be constructed from the static functions of a class.
  31. * @param {boolean=} opt_createProxy An optional argument denoting that
  32. * a proxy for the target mock should be created.
  33. * @constructor
  34. * @extends {goog.testing.Mock}
  35. * @final
  36. */
  37. goog.testing.StrictMock = function(
  38. objectToMock, opt_mockStaticMethods, opt_createProxy) {
  39. goog.testing.Mock.call(
  40. this, objectToMock, opt_mockStaticMethods, opt_createProxy);
  41. /**
  42. * An array of MockExpectations.
  43. * @type {Array<goog.testing.MockExpectation>}
  44. * @private
  45. */
  46. this.$expectations_ = [];
  47. };
  48. goog.inherits(goog.testing.StrictMock, goog.testing.Mock);
  49. /** @override */
  50. goog.testing.StrictMock.prototype.$recordExpectation = function() {
  51. this.$expectations_.push(this.$pendingExpectation);
  52. };
  53. /** @override */
  54. goog.testing.StrictMock.prototype.$recordCall = function(name, args) {
  55. if (this.$expectations_.length == 0) {
  56. this.$throwCallException(name, args);
  57. }
  58. // If the current expectation has a different name, make sure it was called
  59. // enough and then discard it. We're through with it.
  60. var currentExpectation = this.$expectations_[0];
  61. while (!this.$verifyCall(currentExpectation, name, args)) {
  62. // This might be an item which has passed its min, and we can now
  63. // look past it, or it might be below its min and generate an error.
  64. if (currentExpectation.actualCalls < currentExpectation.minCalls) {
  65. this.$throwCallException(name, args, currentExpectation);
  66. }
  67. this.$expectations_.shift();
  68. if (this.$expectations_.length < 1) {
  69. // Nothing left, but this may be a failed attempt to call the previous
  70. // item on the list, which may have been between its min and max.
  71. this.$throwCallException(name, args, currentExpectation);
  72. }
  73. currentExpectation = this.$expectations_[0];
  74. }
  75. if (currentExpectation.maxCalls == 0) {
  76. this.$throwCallException(name, args);
  77. }
  78. currentExpectation.actualCalls++;
  79. // If we hit the max number of calls for this expectation, we're finished
  80. // with it.
  81. if (currentExpectation.actualCalls == currentExpectation.maxCalls) {
  82. this.$expectations_.shift();
  83. }
  84. return this.$do(currentExpectation, args);
  85. };
  86. /** @override */
  87. goog.testing.StrictMock.prototype.$reset = function() {
  88. goog.testing.StrictMock.superClass_.$reset.call(this);
  89. goog.array.clear(this.$expectations_);
  90. };
  91. /** @override */
  92. goog.testing.StrictMock.prototype.$verify = function() {
  93. goog.testing.StrictMock.superClass_.$verify.call(this);
  94. while (this.$expectations_.length > 0) {
  95. var expectation = this.$expectations_[0];
  96. if (expectation.actualCalls < expectation.minCalls) {
  97. this.$throwException(
  98. 'Missing a call to ' + expectation.name + '\nExpected: ' +
  99. expectation.minCalls + ' but was: ' + expectation.actualCalls);
  100. } else {
  101. // Don't need to check max, that's handled when the call is made
  102. this.$expectations_.shift();
  103. }
  104. }
  105. };