sku-pg
Version:
Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!
344 lines (293 loc) • 8.13 kB
HTML
<!DOCTYPE html>
<html>
<!--
Copyright 2008 The Closure Library Authors. All Rights Reserved.
Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Closure Unit Tests - goog.testing.LooseMock</title>
<script src="../base.js"></script>
<script>
goog.require('goog.testing.LooseMock');
goog.require('goog.testing.PropertyReplacer');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.mockmatchers');
</script>
</head>
<body>
<script>
// 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();
assertThrows.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();
assertThrowsQuiet(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);
}
</script>
</body>
</html>