123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629 |
- // Copyright 2012 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.labs.mockTest');
- goog.setTestOnly('goog.labs.mockTest');
- goog.require('goog.array');
- goog.require('goog.labs.mock');
- goog.require('goog.labs.mock.VerificationError');
- /** @suppress {extraRequire} */
- goog.require('goog.labs.testing.AnythingMatcher');
- /** @suppress {extraRequire} */
- goog.require('goog.labs.testing.GreaterThanMatcher');
- goog.require('goog.string');
- goog.require('goog.testing.jsunit');
- var ParentClass = function() {};
- ParentClass.prototype.method1 = function() {};
- ParentClass.prototype.x = 1;
- ParentClass.prototype.val = 0;
- ParentClass.prototype.incrementVal = function() {
- this.val++;
- };
- var ChildClass = function() {};
- goog.inherits(ChildClass, ParentClass);
- ChildClass.prototype.method2 = function() {};
- ChildClass.prototype.y = 2;
- function testParentClass() {
- var parentMock = goog.labs.mock.mock(ParentClass);
- assertNotUndefined(parentMock.method1);
- assertUndefined(parentMock.method1());
- assertUndefined(parentMock.method2);
- assertNotUndefined(parentMock.x);
- assertUndefined(parentMock.y);
- assertTrue(
- 'Mock should be an instance of the mocked class.',
- parentMock instanceof ParentClass);
- }
- function testChildClass() {
- var childMock = goog.labs.mock.mock(ChildClass);
- assertNotUndefined(childMock.method1);
- assertUndefined(childMock.method1());
- assertNotUndefined(childMock.method2);
- assertUndefined(childMock.method2());
- assertNotUndefined(childMock.x);
- assertNotUndefined(childMock.y);
- assertTrue(
- 'Mock should be an instance of the mocked class.',
- childMock instanceof ChildClass);
- }
- function testParentClassInstance() {
- var parentMock = goog.labs.mock.mock(new ParentClass());
- assertNotUndefined(parentMock.method1);
- assertUndefined(parentMock.method1());
- assertUndefined(parentMock.method2);
- assertNotUndefined(parentMock.x);
- assertUndefined(parentMock.y);
- assertTrue(
- 'Mock should be an instance of the mocked class.',
- parentMock instanceof ParentClass);
- }
- function testChildClassInstance() {
- var childMock = goog.labs.mock.mock(new ChildClass());
- assertNotUndefined(childMock.method1);
- assertUndefined(childMock.method1());
- assertNotUndefined(childMock.method2);
- assertUndefined(childMock.method2());
- assertNotUndefined(childMock.x);
- assertNotUndefined(childMock.y);
- assertTrue(
- 'Mock should be an instance of the mocked class.',
- childMock instanceof ParentClass);
- }
- function testNonEnumerableProperties() {
- var mockObject = goog.labs.mock.mock({});
- assertNotUndefined(mockObject.toString);
- goog.labs.mock.when(mockObject).toString().then(function() {
- return 'toString';
- });
- assertEquals('toString', mockObject.toString());
- }
- function testBasicStubbing() {
- var obj = {
- method1: function(i) { return 2 * i; },
- method2: function(i, str) { return str; },
- method3: function(x) { return x; }
- };
- var mockObj = goog.labs.mock.mock(obj);
- goog.labs.mock.when(mockObj).method1(2).then(function(i) { return i; });
- assertEquals(4, obj.method1(2));
- assertEquals(2, mockObj.method1(2));
- assertUndefined(mockObj.method1(4));
- goog.labs.mock.when(mockObj).method2(1, 'hi').then(function(i) {
- return 'oh';
- });
- assertEquals('hi', obj.method2(1, 'hi'));
- assertEquals('oh', mockObj.method2(1, 'hi'));
- assertUndefined(mockObj.method2(3, 'foo'));
- goog.labs.mock.when(mockObj).method3(4).thenReturn(10);
- assertEquals(4, obj.method3(4));
- assertEquals(10, mockObj.method3(4));
- goog.labs.mock.verify(mockObj).method3(4);
- assertUndefined(mockObj.method3(5));
- }
- function testMockFunctions() {
- function x(i) { return i; }
- var mockedFunc = goog.labs.mock.mockFunction(x);
- goog.labs.mock.when(mockedFunc)(100).thenReturn(10);
- goog.labs.mock.when(mockedFunc)(50).thenReturn(25);
- assertEquals(100, x(100));
- assertEquals(10, mockedFunc(100));
- assertEquals(25, mockedFunc(50));
- }
- function testMockFunctionsWithNullableParameters() {
- var func = function(nullableObject) { return 0; };
- var mockedFunc = goog.labs.mock.mockFunction(func);
- goog.labs.mock.when(mockedFunc)(null).thenReturn(-1);
- assertEquals(0, func(null));
- assertEquals(-1, mockedFunc(null));
- }
- function testMockConstructor() {
- var Ctor = function() { this.isMock = false; };
- var mockInstance = {isMock: true};
- var MockCtor = goog.labs.mock.mockConstructor(Ctor);
- goog.labs.mock.when(MockCtor)().thenReturn(mockInstance);
- assertEquals(mockInstance, new MockCtor());
- }
- function testMockConstructorCopiesProperties() {
- var Ctor = function() {};
- Ctor.myParam = true;
- var MockCtor = goog.labs.mock.mockConstructor(Ctor);
- assertTrue(MockCtor.myParam);
- }
- function testStubbingConsecutiveCalls() {
- var obj = {method: function(i) { return i * 42; }};
- var mockObj = goog.labs.mock.mock(obj);
- goog.labs.mock.when(mockObj).method(1).thenReturn(3).thenReturn(4);
- assertEquals(42, obj.method(1));
- assertEquals(3, mockObj.method(1));
- assertEquals(4, mockObj.method(1));
- assertEquals(4, mockObj.method(1));
- var x = function(i) { return i; };
- var mockedFunc = goog.labs.mock.mockFunction(x);
- goog.labs.mock.when(mockedFunc)(100).thenReturn(10).thenReturn(25);
- assertEquals(100, x(100));
- assertEquals(10, mockedFunc(100));
- assertEquals(25, mockedFunc(100));
- assertEquals(25, mockedFunc(100));
- }
- function testStubbingMultipleObjectStubsNonConflictingArgsAllShouldWork() {
- var obj = {method: function(i) { return i * 2; }};
- var mockObj = goog.labs.mock.mock(obj);
- goog.labs.mock.when(mockObj).method(2).thenReturn(100);
- goog.labs.mock.when(mockObj).method(5).thenReturn(45);
- assertEquals(100, mockObj.method(2));
- assertEquals(45, mockObj.method(5));
- }
- function
- testStubbingMultipleObjectStubsConflictingArgsMostRecentShouldPrevail() {
- var obj = {method: function(i) { return i * 2; }};
- var mockObj = goog.labs.mock.mock(obj);
- goog.labs.mock.when(mockObj).method(2).thenReturn(100);
- goog.labs.mock.when(mockObj).method(2).thenReturn(45);
- assertEquals(45, mockObj.method(2));
- }
- function testStubbingMultipleFunctionStubsNonConflictingArgsAllShouldWork() {
- var x = function(i) { return i; };
- var mockedFunc = goog.labs.mock.mockFunction(x);
- goog.labs.mock.when(mockedFunc)(100).thenReturn(10);
- goog.labs.mock.when(mockedFunc)(10).thenReturn(132);
- assertEquals(10, mockedFunc(100));
- assertEquals(132, mockedFunc(10));
- }
- function
- testStubbingMultipleFunctionStubsConflictingArgsMostRecentShouldPrevail() {
- var x = function(i) { return i; };
- var mockedFunc = goog.labs.mock.mockFunction(x);
- goog.labs.mock.when(mockedFunc)(100).thenReturn(10);
- goog.labs.mock.when(mockedFunc)(100).thenReturn(132);
- assertEquals(132, mockedFunc(100));
- }
- function testSpying() {
- var obj = {
- method1: function(i) { return 2 * i; },
- method2: function(i) { return 5 * i; }
- };
- var spyObj = goog.labs.mock.spy(obj);
- goog.labs.mock.when(spyObj).method1(2).thenReturn(5);
- assertEquals(2, obj.method1(1));
- assertEquals(5, spyObj.method1(2));
- goog.labs.mock.verify(spyObj).method1(2);
- assertEquals(2, spyObj.method1(1));
- goog.labs.mock.verify(spyObj).method1(1);
- assertEquals(20, spyObj.method2(4));
- goog.labs.mock.verify(spyObj).method2(4);
- }
- function testSpyParentClassInstance() {
- var parent = new ParentClass();
- var parentMock = goog.labs.mock.spy(parent);
- assertNotUndefined(parentMock.method1);
- assertUndefined(parentMock.method1());
- assertUndefined(parentMock.method2);
- assertNotUndefined(parentMock.x);
- assertUndefined(parentMock.y);
- assertTrue(
- 'Mock should be an instance of the mocked class.',
- parentMock instanceof ParentClass);
- var incrementedOrigVal = parent.val + 1;
- parentMock.incrementVal();
- assertEquals(
- 'Changes in the spied object should reflect in the spy.',
- incrementedOrigVal, parentMock.val);
- }
- function testSpyChildClassInstance() {
- var child = new ChildClass();
- var childMock = goog.labs.mock.spy(child);
- assertNotUndefined(childMock.method1);
- assertUndefined(childMock.method1());
- assertNotUndefined(childMock.method2);
- assertUndefined(childMock.method2());
- assertNotUndefined(childMock.x);
- assertNotUndefined(childMock.y);
- assertTrue(
- 'Mock should be an instance of the mocked class.',
- childMock instanceof ParentClass);
- var incrementedOrigVal = child.val + 1;
- childMock.incrementVal();
- assertEquals(
- 'Changes in the spied object should reflect in the spy.',
- incrementedOrigVal, childMock.val);
- }
- function testVerifyForObjects() {
- var obj = {
- method1: function(i) { return 2 * i; },
- method2: function(i) { return 5 * i; }
- };
- var mockObj = goog.labs.mock.mock(obj);
- goog.labs.mock.when(mockObj).method1(2).thenReturn(5);
- assertEquals(5, mockObj.method1(2));
- goog.labs.mock.verify(mockObj).method1(2);
- var e = assertThrows(goog.partial(goog.labs.mock.verify(mockObj).method2, 2));
- assertTrue(e instanceof goog.labs.mock.VerificationError);
- }
- function testVerifyForFunctions() {
- var func = function(i) { return i; };
- var mockFunc = goog.labs.mock.mockFunction(func);
- goog.labs.mock.when(mockFunc)(2).thenReturn(55);
- assertEquals(55, mockFunc(2));
- goog.labs.mock.verify(mockFunc)(2);
- goog.labs.mock.verify(mockFunc)(lessThan(3));
- var e = assertThrows(goog.partial(goog.labs.mock.verify(mockFunc), 3));
- assertTrue(e instanceof goog.labs.mock.VerificationError);
- }
- function testVerifyForFunctionsWithNullableParameters() {
- var func = function(nullableObject) {};
- var mockFuncCalled = goog.labs.mock.mockFunction(func);
- var mockFuncNotCalled = goog.labs.mock.mockFunction(func);
- mockFuncCalled(null);
- goog.labs.mock.verify(mockFuncCalled)(null);
- var e = assertThrows(
- goog.partial(goog.labs.mock.verify(mockFuncNotCalled), null));
- assertTrue(e instanceof goog.labs.mock.VerificationError);
- }
- function testVerifyPassesWhenVerificationModeReturnsTrue() {
- var trueMode = {
- verify: function(number) { return true; },
- describe: function() { return ''; }
- };
- var mockObj = goog.labs.mock.mock({doThing: function() {}});
- goog.labs.mock.verify(mockObj, trueMode).doThing();
- }
- function testVerifyFailsWhenVerificationModeReturnsFalse() {
- var falseMode = {
- verify: function(number) { return false; },
- describe: function() { return ''; }
- };
- var mockObj = goog.labs.mock.mock({doThing: function() {}});
- assertThrows(goog.labs.mock.verify(mockObj, falseMode).doThing);
- }
- function testVerificationErrorMessagePutsVerificationModeInRightPlace() {
- var modeDescription = 'test';
- var mode = {
- verify: function(number) { return false; },
- describe: function() { return modeDescription; }
- };
- var mockObj = goog.labs.mock.mock({methodName: function() {}});
- mockObj.methodName(2);
- e = assertThrows(goog.labs.mock.verify(mockObj, mode).methodName);
- // The mode description should be between the expected method
- // invocation and a newline.
- assertTrue(goog.string.contains(
- e.message, 'methodName() ' + modeDescription + '\n'));
- }
- /**
- * When a function invocation verification fails, it should show the failed
- * expectation call, as well as the recorded calls to the same method.
- */
- function testVerificationErrorMessages() {
- var mock = goog.labs.mock.mock({method: function(i) { return i; }});
- // Failure when there are no recorded calls.
- var e = assertThrows(function() { goog.labs.mock.verify(mock).method(4); });
- assertTrue(e instanceof goog.labs.mock.VerificationError);
- var expected = '\nExpected: method(4) at least 1 times\n' +
- 'Recorded: No recorded calls';
- assertEquals(expected, e.message);
- // Failure when there are recorded calls with ints and functions
- // as arguments.
- var callback = function() {};
- var callbackId = goog.labs.mock.getUid(callback);
- mock.method(1);
- mock.method(2);
- mock.method(callback);
- e = assertThrows(function() { goog.labs.mock.verify(mock).method(3); });
- assertTrue(e instanceof goog.labs.mock.VerificationError);
- expected = '\nExpected: method(3) at least 1 times\n' +
- 'Recorded: method(1),\n' +
- ' method(2),\n' +
- ' method(<function #anonymous' + callbackId + '>)';
- assertEquals(expected, e.message);
- // With mockFunctions
- var mockCallback = goog.labs.mock.mockFunction(callback);
- e = assertThrows(function() { goog.labs.mock.verify(mockCallback)(5); });
- expected = '\nExpected: #mockFor<#anonymous' + callbackId + '>(5) at least' +
- ' 1 times\n' +
- 'Recorded: No recorded calls';
- mockCallback(8);
- goog.labs.mock.verify(mockCallback)(8);
- assertEquals(expected, e.message);
- // Objects with circular references should not fail.
- var obj = {x: 1};
- obj.y = obj;
- mockCallback(obj);
- e = assertThrows(function() { goog.labs.mock.verify(mockCallback)(5); });
- assertTrue(e instanceof goog.labs.mock.VerificationError);
- // Should respect string representation of different custom classes.
- var myClass = function() {};
- myClass.prototype.toString = function() { return '<superClass>'; };
- var mockFunction = goog.labs.mock.mockFunction(function f() {});
- mockFunction(new myClass());
- e = assertThrows(function() { goog.labs.mock.verify(mockFunction)(5); });
- expected = '\nExpected: #mockFor<f>(5) at least 1 times\n' +
- 'Recorded: #mockFor<f>(<superClass>)';
- assertEquals(expected, e.message);
- }
- /**
- * Asserts that the given string contains a list of others strings
- * in the given order.
- */
- function assertContainsInOrder(str, var_args) {
- var expected = goog.array.splice(arguments, 1);
- var indices =
- goog.array.map(expected, function(val) { return str.indexOf(val); });
- for (var i = 0; i < expected.length; i++) {
- var msg = 'Missing "' + expected[i] + '" from "' + str + '"';
- assertTrue(msg, indices[i] != -1);
- if (i > 0) {
- msg = '"' + expected[i - 1] + '" should come before "' + expected[i] +
- '" in "' + str + '"';
- assertTrue(msg, indices[i] > indices[i - 1]);
- }
- }
- }
- function testMatchers() {
- var obj = {
- method1: function(i) { return 2 * i; },
- method2: function(i) { return 5 * i; }
- };
- var mockObj = goog.labs.mock.mock(obj);
- goog.labs.mock.when(mockObj).method1(greaterThan(4)).thenReturn(100);
- goog.labs.mock.when(mockObj).method1(lessThan(4)).thenReturn(40);
- assertEquals(100, mockObj.method1(5));
- assertEquals(100, mockObj.method1(6));
- assertEquals(40, mockObj.method1(2));
- assertEquals(40, mockObj.method1(1));
- assertUndefined(mockObj.method1(4));
- }
- function testMatcherVerify() {
- var obj = {method: function(i) { return 2 * i; }};
- // Using spy objects.
- var spy = goog.labs.mock.spy(obj);
- spy.method(6);
- goog.labs.mock.verify(spy).method(greaterThan(4));
- var e = assertThrows(
- goog.partial(goog.labs.mock.verify(spy).method, lessThan(4)));
- assertTrue(e instanceof goog.labs.mock.VerificationError);
- // Using mocks
- var mockObj = goog.labs.mock.mock(obj);
- mockObj.method(8);
- goog.labs.mock.verify(mockObj).method(greaterThan(7));
- var e = assertThrows(
- goog.partial(goog.labs.mock.verify(mockObj).method, lessThan(7)));
- assertTrue(e instanceof goog.labs.mock.VerificationError);
- }
- function testMatcherVerifyCollision() {
- var obj = {method: function(i) { return 2 * i; }};
- var mockObj = goog.labs.mock.mock(obj);
- goog.labs.mock.when(mockObj).method(5).thenReturn(100);
- assertNotEquals(100, mockObj.method(greaterThan(2)));
- }
- function testMatcherVerifyCollisionBetweenMatchers() {
- var obj = {method: function(i) { return 2 * i; }};
- var mockObj = goog.labs.mock.mock(obj);
- goog.labs.mock.when(mockObj).method(anything()).thenReturn(100);
- var e = assertThrows(
- goog.partial(goog.labs.mock.verify(mockObj).method, anything()));
- assertTrue(e instanceof goog.labs.mock.VerificationError);
- }
- function testVerifyForUnmockedMethods() {
- var Task = function() {};
- Task.prototype.run = function() {};
- var mockTask = goog.labs.mock.mock(Task);
- mockTask.run();
- goog.labs.mock.verify(mockTask).run();
- }
- function testFormatMethodCall() {
- var formatMethodCall = goog.labs.mock.formatMethodCall_;
- assertEquals('alert()', formatMethodCall('alert'));
- assertEquals('sum(2, 4)', formatMethodCall('sum', [2, 4]));
- assertEquals('sum("2", "4")', formatMethodCall('sum', ['2', '4']));
- assertEquals(
- 'call(<function unicorn>)',
- formatMethodCall('call', [function unicorn() {}]));
- var arg = {x: 1, y: {hello: 'world'}};
- assertEquals(
- 'call(' + goog.labs.mock.formatValue_(arg) + ')',
- formatMethodCall('call', [arg]));
- }
- function testGetFunctionName() {
- var f1 = function() {};
- var f2 = function() {};
- var named = function myName() {};
- assert(
- goog.string.startsWith(
- goog.labs.mock.getFunctionName_(f1), '#anonymous'));
- assert(
- goog.string.startsWith(
- goog.labs.mock.getFunctionName_(f2), '#anonymous'));
- assertNotEquals(
- goog.labs.mock.getFunctionName_(f1), goog.labs.mock.getFunctionName_(f2));
- assertEquals('myName', goog.labs.mock.getFunctionName_(named));
- }
- function testFormatObject() {
- var obj, obj2, obj3;
- obj = {x: 1};
- assertEquals(
- '{"x":1 _id:' + goog.labs.mock.getUid(obj) + '}',
- goog.labs.mock.formatValue_(obj));
- assertEquals('{"x":1}', goog.labs.mock.formatValue_(obj, false /* id */));
- obj = {x: 'hello'};
- assertEquals(
- '{"x":"hello" _id:' + goog.labs.mock.getUid(obj) + '}',
- goog.labs.mock.formatValue_(obj));
- assertEquals(
- '{"x":"hello"}', goog.labs.mock.formatValue_(obj, false /* id */));
- obj3 = {};
- obj2 = {y: obj3};
- obj3.x = obj2;
- assertEquals(
- '{"x":{"y":<recursive/dupe obj_' + goog.labs.mock.getUid(obj3) + '> ' +
- '_id:' + goog.labs.mock.getUid(obj2) + '} ' +
- '_id:' + goog.labs.mock.getUid(obj3) + '}',
- goog.labs.mock.formatValue_(obj3));
- assertEquals(
- '{"x":{"y":<recursive/dupe>}}',
- goog.labs.mock.formatValue_(obj3, false /* id */));
- obj = {x: function y() {}};
- assertEquals(
- '{"x":<function y> _id:' + goog.labs.mock.getUid(obj) + '}',
- goog.labs.mock.formatValue_(obj));
- assertEquals(
- '{"x":<function y>}', goog.labs.mock.formatValue_(obj, false /* id */));
- }
- function testGetUid() {
- var obj1 = {};
- var obj2 = {};
- var func1 = function() {};
- var func2 = function() {};
- assertNotEquals(goog.labs.mock.getUid(obj1), goog.labs.mock.getUid(obj2));
- assertNotEquals(goog.labs.mock.getUid(func1), goog.labs.mock.getUid(func2));
- assertNotEquals(goog.labs.mock.getUid(obj1), goog.labs.mock.getUid(func2));
- assertEquals(goog.labs.mock.getUid(obj1), goog.labs.mock.getUid(obj1));
- assertEquals(goog.labs.mock.getUid(func1), goog.labs.mock.getUid(func1));
- }
- 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 mockObj = goog.labs.mock.mock(Foo);
- goog.labs.mock.when(mockObj).a().thenReturn('a');
- assertThrowsJsUnitException(function() { new Foo().a(); });
- assertEquals('a', mockObj.a());
- goog.labs.mock.verify(mockObj).a();
- }
|