123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- // 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.LooseMockTest');
- goog.setTestOnly('goog.testing.LooseMockTest');
- goog.require('goog.testing.LooseMock');
- goog.require('goog.testing.PropertyReplacer');
- goog.require('goog.testing.jsunit');
- goog.require('goog.testing.mockmatchers');
- // 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 mock;
- var stubs;
- function setUp() {
- var obj = new RealObject();
- mock = new goog.testing.LooseMock(obj);
- stubs = new goog.testing.PropertyReplacer();
- }
- function tearDown() {
- stubs.reset();
- }
- /*
- * Calling this method evades the logTestFailure in
- * goog.testing.Mock.prototype.$recordAndThrow, so it doesn't look like the
- * test failed.
- */
- function silenceFailureLogging() {
- if (goog.global['G_testRunner']) {
- stubs.set(goog.global['G_testRunner'], 'logTestFailure', goog.nullFunction);
- }
- }
- function unsilenceFailureLogging() {
- stubs.reset();
- }
- /**
- * Version of assertThrows that doesn't log the exception generated by the
- * mocks under test.
- * TODO: would be nice to check that a particular substring is in the thrown
- * message so we know it's not something dumb like a syntax error
- */
- function assertThrowsQuiet(var_args) {
- silenceFailureLogging();
- assertThrowsJsUnitException.apply(null, arguments);
- unsilenceFailureLogging();
- }
- // Most of the basic functionality is tested in strictmock_test; these tests
- // cover the cases where loose mocks are different from strict mocks
- function testSimpleExpectations() {
- mock.a(5);
- mock.b();
- mock.$replay();
- mock.a(5);
- mock.b();
- mock.$verify();
- mock.$reset();
- mock.a();
- mock.b();
- mock.$replay();
- mock.b();
- mock.a();
- mock.$verify();
- mock.$reset();
- mock.a(5).$times(2);
- mock.a(5);
- mock.a(2);
- mock.$replay();
- mock.a(5);
- mock.a(5);
- mock.a(5);
- mock.a(2);
- mock.$verify();
- }
- function testMultipleExpectations() {
- mock.a().$returns(1);
- mock.a().$returns(2);
- mock.$replay();
- assertEquals(1, mock.a());
- assertEquals(2, mock.a());
- mock.$verify();
- }
- function testMultipleExpectationArgs() {
- mock.a('asdf').$anyTimes();
- mock.a('qwer').$anyTimes();
- mock.b().$times(3);
- mock.$replay();
- mock.a('asdf');
- mock.b();
- mock.a('asdf');
- mock.a('qwer');
- mock.b();
- mock.a('qwer');
- mock.b();
- mock.$verify();
- mock.$reset();
- mock.a('asdf').$anyTimes();
- mock.a('qwer').$anyTimes();
- mock.$replay();
- mock.a('asdf');
- mock.a('qwer');
- goog.bind(mock.a, mock, 'asdf');
- goog.bind(mock.$verify, mock);
- }
- function testSameMethodOutOfOrder() {
- mock.a('foo').$returns(1);
- mock.a('bar').$returns(2);
- mock.$replay();
- assertEquals(2, mock.a('bar'));
- assertEquals(1, mock.a('foo'));
- }
- function testSameMethodDifferentReturnValues() {
- mock.a('foo').$returns(1).$times(2);
- mock.a('foo').$returns(3);
- mock.a('bar').$returns(2);
- mock.$replay();
- assertEquals(1, mock.a('foo'));
- assertEquals(2, mock.a('bar'));
- assertEquals(1, mock.a('foo'));
- assertEquals(3, mock.a('foo'));
- assertThrowsQuiet(function() {
- mock.a('foo');
- mock.$verify();
- });
- }
- function testSameMethodBrokenExpectations() {
- // This is a weird corner case.
- // No way to ever make this verify no matter what you call after replaying,
- // because the second expectation of mock.a('foo') will be masked by
- // the first expectation that can be called any number of times, and so we
- // can never satisfy that second expectation.
- mock.a('foo').$returns(1).$anyTimes();
- mock.a('bar').$returns(2);
- mock.a('foo').$returns(3);
- // LooseMock can detect this case and fail on $replay.
- assertThrowsQuiet(goog.bind(mock.$replay, mock));
- mock.$reset();
- // This is a variant of the corner case above, but it's harder to determine
- // that the expectation to mock.a('bar') can never be satisfied. So we don't
- // fail on $replay, but we do fail on $verify.
- mock.a(goog.testing.mockmatchers.isString).$returns(1).$anyTimes();
- mock.a('bar').$returns(2);
- mock.$replay();
- assertEquals(1, mock.a('foo'));
- assertEquals(1, mock.a('bar'));
- assertThrowsQuiet(goog.bind(mock.$verify, mock));
- }
- function testSameMethodMultipleAnyTimes() {
- mock.a('foo').$returns(1).$anyTimes();
- mock.a('foo').$returns(2).$anyTimes();
- mock.$replay();
- assertEquals(1, mock.a('foo'));
- assertEquals(1, mock.a('foo'));
- assertEquals(1, mock.a('foo'));
- // Note we'll never return 2 but that's ok.
- mock.$verify();
- }
- function testFailingFast() {
- mock.a().$anyTimes();
- mock.$replay();
- mock.a();
- mock.a();
- assertThrowsQuiet(goog.bind(mock.b, mock));
- mock.$reset();
- // too many
- mock.a();
- mock.b();
- mock.$replay();
- mock.a();
- mock.b();
- var message;
- silenceFailureLogging();
- try {
- mock.a();
- } catch (e) {
- message = e.message;
- }
- unsilenceFailureLogging();
- assertTrue('No exception thrown on unexpected call', goog.isDef(message));
- assertContains('Too many calls to a', message);
- }
- function testTimes() {
- mock.a().$times(3);
- mock.b().$times(2);
- mock.$replay();
- mock.a();
- mock.b();
- mock.b();
- mock.a();
- mock.a();
- mock.$verify();
- }
- function testFailingSlow() {
- // not enough
- mock.a().$times(3);
- mock.$replay();
- mock.a();
- mock.a();
- assertThrowsQuiet(goog.bind(mock.$verify, mock));
- mock.$reset();
- // not enough, interleaved order
- mock.a().$times(3);
- mock.b().$times(3);
- mock.$replay();
- mock.a();
- mock.b();
- mock.a();
- mock.b();
- assertThrowsQuiet(goog.bind(mock.$verify, mock));
- mock.$reset();
- // bad args
- mock.a('asdf').$anyTimes();
- mock.$replay();
- mock.a('asdf');
- assertThrowsQuiet(goog.bind(mock.a, mock, 'qwert'));
- assertThrowsQuiet(goog.bind(mock.$verify, mock));
- }
- function testArgsAndReturns() {
- mock.a('asdf').$atLeastOnce().$returns(5);
- mock.b('qwer').$times(2).$returns(3);
- mock.$replay();
- assertEquals(5, mock.a('asdf'));
- assertEquals(3, mock.b('qwer'));
- assertEquals(5, mock.a('asdf'));
- assertEquals(5, mock.a('asdf'));
- assertEquals(3, mock.b('qwer'));
- mock.$verify();
- }
- function testThrows() {
- mock.a().$throws('exception!');
- mock.$replay();
- assertThrows(goog.bind(mock.a, mock));
- mock.$verify();
- }
- function testDoes() {
- mock.a(1, 2).$does(function(a, b) { return a + b; });
- mock.$replay();
- assertEquals('Mock should call the function', 3, mock.a(1, 2));
- mock.$verify();
- }
- function testIgnoresExtraCalls() {
- mock = new goog.testing.LooseMock(RealObject, true);
- mock.a();
- mock.$replay();
- mock.a();
- mock.b(); // doesn't throw
- mock.$verify();
- }
- function testSkipAnyTimes() {
- mock = new goog.testing.LooseMock(RealObject);
- mock.a(1).$anyTimes();
- mock.a(2).$anyTimes();
- mock.a(3).$anyTimes();
- mock.$replay();
- mock.a(1);
- mock.a(3);
- mock.$verify();
- }
- function testErrorMessageForBadArgs() {
- mock.a();
- mock.$anyTimes();
- mock.$replay();
- var message;
- silenceFailureLogging();
- try {
- mock.a('a');
- } catch (e) {
- message = e.message;
- }
- unsilenceFailureLogging();
- assertTrue('No exception thrown on verify', goog.isDef(message));
- assertContains('Bad arguments to a()', message);
- }
|