1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * Create a mock function that records function calls and validates against
10 function MockMethod() {
12 var args
= Array
.prototype.slice
.call(arguments
);
14 args
.filter(function(arg
) { return (typeof arg
== 'function'); });
16 if (callbacks
.length
> 1) {
17 console
.error('Only support mocking function with at most one callback.');
22 if (callbacks
.length
== 1) {
23 callbacks
[0].apply(undefined, fn
.callbackData
);
26 return fn
.returnValue
;
30 * List of signatures for fucntion calls.
31 * @type {!Array<!Array>}
37 * List of expected call signatures.
38 * @type {!Array<!Array>}
41 fn
.expectations_
= [];
44 * Value returned from call to function.
47 fn
.returnValue
= undefined;
50 * List of arguments for callback function.
51 * @type {!Array<!Array>}
55 fn
.__proto__
= MockMethod
.prototype;
59 MockMethod
.prototype = {
61 * Adds an expected call signature.
62 * @param {...} var_args Expected arguments for the function call.
64 addExpectation: function() {
65 var args
= Array
.prototype.slice
.call(arguments
);
66 this.expectations_
.push(args
.filter(this.notFunction_
));
70 * Adds a call signature.
71 * @param {!Array} args.
73 recordCall: function(args
) {
74 this.calls_
.push(args
.filter(this.notFunction_
));
78 * Verifies that the function is called the expected number of times and with
79 * the correct signature for each call.
81 verifyMock: function() {
82 var errorMessage
= 'Number of method calls did not match expectation.';
83 if (this.functionName
)
84 errorMessage
= 'Error in ' + this.functionName
+ ':\n' + errorMessage
;
85 assertEquals(this.expectations_
.length
,
88 for (var i
= 0; i
< this.expectations_
.length
; i
++) {
89 this.validateCall(i
, this.expectations_
[i
], this.calls_
[i
]);
94 * Verifies that the observed function arguments match expectations.
95 * Override if strict equality is not required.
96 * @param {number} index Canonical index of the function call. Unused in the
97 * base implementation, but provides context that may be useful for
99 * @param {!Array} expected The expected arguments.
100 * @parma {!Array} observed The observed arguments.
102 validateCall: function(index
, expected
, observed
) {
103 assertDeepEquals(expected
, observed
);
107 * Test if arg is a function.
108 * @param {*} arg The argument to test.
109 * @return True if arg is not function type.
111 notFunction_: function(arg
) {
112 return typeof arg
!= 'function';
117 * Controller for mocking methods. Tracks calls to mocked methods and verifies
118 * that call signatures match expectations.
121 function MockController() {
123 * Original functions implementations, which are restored when |reset| is
125 * @type {!Array<!Object>}
128 this.overrides_
= [];
131 * List of registered mocks.
132 * @type {!Array<!MockMethod>}
138 MockController
.prototype = {
140 * Creates a mock function.
141 * @param {Object=} opt_parent Optional parent object for the function.
142 * @param {string=} opt_functionName Optional name of the function being
143 * mocked. If the parent and function name are both provided, the
144 * mock is automatically substituted for the original and replaced on
147 createFunctionMock: function(opt_parent
, opt_functionName
) {
148 var fn
= new MockMethod();
151 if (opt_parent
&& opt_functionName
) {
152 this.overrides_
.push({
154 functionName
: opt_functionName
,
155 originalFunction
: opt_parent
[opt_functionName
]
157 opt_parent
[opt_functionName
] = fn
;
158 fn
.functionName
= opt_functionName
;
160 this.mocks_
.push(fn
);
166 * Validates all mocked methods. An exception is thrown if the
167 * expected and actual calls to a mocked function to not align.
169 verifyMocks: function() {
170 for (var i
= 0; i
< this.mocks_
.length
; i
++) {
171 this.mocks_
[i
].verifyMock();
176 * Discard mocks reestoring default behavior.
179 for (var i
= 0; i
< this.overrides_
.length
; i
++) {
180 var override
= this.overrides_
[i
];
181 override
.parent
[override
.functionName
] = override
.originalFunction
;