123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- // Copyright 2008 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- goog.provide('goog.testing.MockTest');
- goog.setTestOnly('goog.testing.MockTest');
- goog.require('goog.array');
- goog.require('goog.testing');
- goog.require('goog.testing.Mock');
- goog.require('goog.testing.MockControl');
- goog.require('goog.testing.MockExpectation');
- goog.require('goog.testing.jsunit');
- // The object that we will be mocking
- var RealObject = function() {};
- RealObject.prototype.a = function() {
- fail('real object should never be called');
- };
- RealObject.prototype.b = function() {
- fail('real object should never be called');
- };
- var matchers = goog.testing.mockmatchers;
- var mock;
- function setUp() {
- var obj = new RealObject();
- mock = new goog.testing.Mock(obj);
- }
- function testMockErrorMessage() {
- var expectation = new goog.testing.MockExpectation('a');
- assertEquals(0, expectation.getErrorMessageCount());
- assertEquals('', expectation.getErrorMessage());
- expectation.addErrorMessage('foo failed');
- assertEquals(1, expectation.getErrorMessageCount());
- assertEquals('foo failed', expectation.getErrorMessage());
- expectation.addErrorMessage('bar failed');
- assertEquals(2, expectation.getErrorMessageCount());
- assertEquals('foo failed\nbar failed', expectation.getErrorMessage());
- }
- function testVerifyArgumentList() {
- var expectation = new goog.testing.MockExpectation('a');
- assertEquals('', expectation.getErrorMessage());
- // test single string arg
- expectation.argumentList = ['foo'];
- assertTrue(mock.$verifyCall(expectation, 'a', ['foo']));
- // single numeric arg
- expectation.argumentList = [2];
- assertTrue(mock.$verifyCall(expectation, 'a', [2]));
- // single object arg (using standard === comparison)
- var obj = {prop1: 'prop1', prop2: 2};
- expectation.argumentList = [obj];
- assertTrue(mock.$verifyCall(expectation, 'a', [obj]));
- // make sure comparison succeeds if args are similar, but not ===
- var obj2 = {prop1: 'prop1', prop2: 2};
- expectation.argumentList = [obj];
- assertTrue(mock.$verifyCall(expectation, 'a', [obj2]));
- assertEquals('', expectation.getErrorMessage());
- // multiple args
- expectation.argumentList = ['foo', 2, obj, obj2];
- assertTrue(mock.$verifyCall(expectation, 'a', ['foo', 2, obj, obj2]));
- // test flexible arg matching.
- expectation.argumentList = ['foo', matchers.isNumber];
- assertTrue(mock.$verifyCall(expectation, 'a', ['foo', 1]));
- expectation.argumentList = [new matchers.InstanceOf(RealObject)];
- assertTrue(mock.$verifyCall(expectation, 'a', [new RealObject()]));
- }
- function testVerifyArgumentListForObjectMethods() {
- var expectation = new goog.testing.MockExpectation('toString');
- expectation.argumentList = [];
- assertTrue(mock.$verifyCall(expectation, 'toString', []));
- }
- function testRegisterArgumentListVerifier() {
- var expectationA = new goog.testing.MockExpectation('a');
- var expectationB = new goog.testing.MockExpectation('b');
- // Simple matcher that return true if all args are === equivalent.
- mock.$registerArgumentListVerifier('a', function(expectedArgs, args) {
- return goog.array.equals(
- expectedArgs, args, function(a, b) { return (a === b); });
- });
- // test single string arg
- expectationA.argumentList = ['foo'];
- assertTrue(mock.$verifyCall(expectationA, 'a', ['foo']));
- // single numeric arg
- expectationA.argumentList = [2];
- assertTrue(mock.$verifyCall(expectationA, 'a', [2]));
- // single object arg (using standard === comparison)
- var obj = {prop1: 'prop1', prop2: 2};
- expectationA.argumentList = [obj];
- expectationB.argumentList = [obj];
- assertTrue(mock.$verifyCall(expectationA, 'a', [obj]));
- assertTrue(mock.$verifyCall(expectationB, 'b', [obj]));
- // if args are similar, but not ===, then comparison should succeed
- // for method with registered object matcher, and fail for method without
- var obj2 = {prop1: 'prop1', prop2: 2};
- expectationA.argumentList = [obj];
- expectationB.argumentList = [obj];
- assertFalse(mock.$verifyCall(expectationA, 'a', [obj2]));
- assertTrue(mock.$verifyCall(expectationB, 'b', [obj2]));
- // multiple args, should fail for method with registered arg matcher,
- // and succeed for method without.
- expectationA.argumentList = ['foo', 2, obj, obj2];
- expectationB.argumentList = ['foo', 2, obj, obj2];
- assertFalse(mock.$verifyCall(expectationA, 'a', ['foo', 2, obj2, obj]));
- assertTrue(mock.$verifyCall(expectationB, 'b', ['foo', 2, obj2, obj]));
- }
- function testCreateProxy() {
- mock = new goog.testing.Mock(RealObject, false, true);
- assertTrue(mock.$proxy instanceof RealObject);
- assertThrows(function() { new goog.testing.Mock(RealObject, true, true); });
- assertThrows(function() { new goog.testing.Mock(1, false, true); });
- }
- function testValidConstructorArgument() {
- var someNamespace = {};
- assertThrows(function() {
- new goog.testing.Mock(someNamespace.RealObjectWithTypo);
- });
- }
- function testArgumentsAsString() {
- assertEquals('()', mock.$argumentsAsString([]));
- assertEquals(
- '(string, number, object, null)',
- mock.$argumentsAsString(['red', 1, {}, null]));
- }
- function testThrowCallExceptionBadArgs() {
- var msg;
- mock.$throwException = function(m) { msg = m; };
- mock.$throwCallException('fn1', ['b'], {
- name: 'fn1',
- argumentList: ['c'],
- getErrorMessage: function() { return ''; }
- });
- assertContains(
- 'Bad arguments to fn1().\nActual: (string)\nExpected: (string)', msg);
- }
- function testThrowCallExceptionUnexpected() {
- var msg;
- mock.$throwException = function(m) { msg = m; };
- mock.$throwCallException('fn1', ['b']);
- assertEquals('Unexpected call to fn1(string).', msg);
- }
- function testThrowCallExceptionUnexpectedWithNext() {
- var msg;
- mock.$throwException = function(m) { msg = m; };
- mock.$throwCallException('fn1', ['b'], {
- name: 'fn2',
- argumentList: [3],
- getErrorMessage: function() { return ''; }
- });
- assertEquals(
- 'Unexpected call to fn1(string).\n' +
- 'Next expected call was to fn2(number)',
- msg);
- }
- // This tests that base Object functions which are not enumerable in IE can
- // be mocked correctly.
- function testBindNonEnumerableFunctions() {
- // Create Foo and override non enumerable functions.
- var Foo = function() {};
- Foo.prototype.constructor = function() {
- fail('real object should never be called');
- };
- Foo.prototype.hasOwnProperty = function() {
- fail('real object should never be called');
- };
- Foo.prototype.isPrototypeOf = function() {
- fail('real object should never be called');
- };
- Foo.prototype.propertyIsEnumerable = function() {
- fail('real object should never be called');
- };
- Foo.prototype.toLocaleString = function() {
- fail('real object should never be called');
- };
- Foo.prototype.toString = function() {
- fail('real object should never be called');
- };
- Foo.prototype.valueOf = function() {
- fail('real object should never be called');
- };
- // Create Mock and set $returns for toString.
- var mockControl = new goog.testing.MockControl();
- var mock = mockControl.createLooseMock(Foo);
- mock.constructor().$returns('constructor');
- mock.hasOwnProperty().$returns('hasOwnProperty');
- mock.isPrototypeOf().$returns('isPrototypeOf');
- mock.propertyIsEnumerable().$returns('propertyIsEnumerable');
- mock.toLocaleString().$returns('toLocaleString');
- mock.toString().$returns('toString');
- mock.valueOf().$returns('valueOf');
- // Execute and assert that the Mock is working correctly.
- mockControl.$replayAll();
- assertEquals('constructor', mock.constructor());
- assertEquals('hasOwnProperty', mock.hasOwnProperty());
- assertEquals('isPrototypeOf', mock.isPrototypeOf());
- assertEquals('propertyIsEnumerable', mock.propertyIsEnumerable());
- assertEquals('toLocaleString', mock.toLocaleString());
- assertEquals('toString', mock.toString());
- assertEquals('valueOf', mock.valueOf());
- mockControl.$verifyAll();
- }
- function testMockInheritedMethods() {
- var SubType = function() {};
- goog.inherits(SubType, RealObject);
- SubType.prototype.c = function() {
- fail('real object should never be called');
- };
- var mockControl = new goog.testing.MockControl();
- var mock = mockControl.createLooseMock(SubType);
- mock.a().$returns('a');
- mock.b().$returns('b');
- mock.c().$returns('c');
- // Execute and assert that the Mock is working correctly.
- mockControl.$replayAll();
- assertEquals('a', mock.a());
- assertEquals('b', mock.b());
- assertEquals('c', mock.c());
- mockControl.$verifyAll();
- }
- function testMockStaticMethods() {
- var SomeType = function() {};
- SomeType.staticMethod = function() {
- fail('real object should never be called');
- };
- var mockControl = new goog.testing.MockControl();
- var mock = mockControl.createLooseMock(
- SomeType, false /* opt_ignoreUnexpectedCalls */,
- true /* opt_mockStaticMethods */);
- mock.staticMethod().$returns('staticMethod');
- // Execute and assert that the Mock is working correctly.
- mockControl.$replayAll();
- assertEquals('staticMethod', mock.staticMethod());
- mockControl.$verifyAll();
- }
- function testMockEs6ClassMethods() {
- // Create an ES6 class via eval so we can bail out if it's a syntax error in
- // browsers that don't support ES6 classes.
- try {
- eval(
- 'var Foo = class {' +
- ' a() {' +
- ' fail(\'real object should never be called\');' +
- ' }' +
- '}');
- } catch (e) {
- if (e instanceof SyntaxError) {
- return;
- }
- }
- var mockControl = new goog.testing.MockControl();
- var mock = mockControl.createLooseMock(Foo);
- mock.a().$returns('a');
- // Execute and assert that the Mock is working correctly.
- mockControl.$replayAll();
- assertEquals('a', mock.a());
- mockControl.$verifyAll();
- }
- function testMockEs6ClassStaticMethods() {
- // Create an ES6 class via eval so we can bail out if it's a syntax error in
- // browsers that don't support ES6 classes.
- try {
- eval(
- 'var Foo = class {' +
- ' static a() {' +
- ' fail(\'real object should never be called\');' +
- ' }' +
- ' static apply() {' +
- ' fail(\'real object should never be called\');' +
- ' }' +
- '}');
- } catch (e) {
- if (e instanceof SyntaxError) {
- return;
- }
- }
- var mockControl = new goog.testing.MockControl();
- var mock = mockControl.createLooseMock(
- Foo, false /* opt_ignoreUnexpectedCalls */,
- true /* opt_mockStaticMethods */);
- mock.a().$returns('a');
- mock.apply().$returns('apply');
- // Execute and assert that the Mock is working correctly.
- mockControl.$replayAll();
- assertEquals('a', mock.a());
- assertEquals('apply', mock.apply());
- mockControl.$verifyAll();
- }
|