Add a top-level typed_mock package.

R=brianwilkerson@google.com, danrubel@google.com
BUG=

Review URL: https://codereview.chromium.org//281943002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36170 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
scheglov@google.com 2014-05-14 15:36:18 +00:00
parent 839e807406
commit 8efee14586
4 changed files with 84 additions and 35 deletions

View file

@ -10,7 +10,6 @@ import 'domain_context_test.dart' as domain_context_test;
import 'domain_server_test.dart' as domain_server_test;
import 'protocol_test.dart' as protocol_test;
import 'socket_server_test.dart' as socket_server_test;
import 'typed_mock_test.dart' as typed_mock_test;
/// Utility for manually running all tests
main() {
@ -21,6 +20,5 @@ main() {
domain_server_test.main();
protocol_test.main();
socket_server_test.main();
typed_mock_test.main();
});
}

View file

@ -3,10 +3,28 @@ library typed_mock;
_InvocationMatcher _lastMatcher;
/// Enables stubbing methods.
/// Use it when you want the mock to return particular value when particular
/// method is called.
///
/// Use it when you want the mock to return a particular value when a particular
/// method, getter or setter is called.
///
/// when(obj.testProperty).thenReturn(10);
/// expect(obj.testProperty, 10); // pass
///
/// You can specify multiple matchers, which are checked one after another.
///
/// when(obj.testMethod(anyInt)).thenReturn('was int');
/// when(obj.testMethod(anyString)).thenReturn('was String');
/// expect(obj.testMethod(42), 'was int'); // pass
/// expect(obj.testMethod('foo'), 'was String'); // pass
///
/// You can even provide a function to calculate results.
/// Function can be also used to capture invocation arguments (if you test some
/// consumer).
///
/// when(obj.testMethod(anyInt)).thenInvoke((int p) => 10 + p);
/// expect(obj.testMethod(1), 11); // pass
/// expect(obj.testMethod(5), 15); // pass
Behavior when(_ignored) {
try {
var mock = _lastMatcher._mock;
@ -111,7 +129,7 @@ class _InvocationMatcher {
for (int i = 0; i < _matchers.length; i++) {
var matcher = _matchers[i];
var argument = arguments[i];
if (!matcher.match(argument)) {
if (!matcher.matches(argument)) {
return false;
}
}
@ -138,6 +156,7 @@ class Behavior {
bool _throwExceptionEnabled = false;
var _throwException;
/// Invokes the given [function] with actual arguments and returns its result.
Behavior thenInvoke(Function function) {
_reset();
_thenFunctionEnabled = true;
@ -145,6 +164,7 @@ class Behavior {
return this;
}
/// Returns the specific value.
Behavior thenReturn(value) {
_reset();
_returnAlwaysEnabled = true;
@ -152,6 +172,8 @@ class Behavior {
return this;
}
/// Returns values from the [list] starting from first to the last.
/// If the end of list is reached a [StateError] is thrown.
Behavior thenReturnList(List list) {
_reset();
_returnListEnabled = true;
@ -160,6 +182,7 @@ class Behavior {
return this;
}
/// Throws the specified [exception] object.
Behavior thenThrow(exception) {
_reset();
_throwExceptionEnabled = true;
@ -283,6 +306,17 @@ class Verifier {
}
/// A class to extend mocks from.
/// It supports specifying behavior using [when] and validation of interactions
/// using [verify].
///
/// abstract class Name {
/// String get firstName;
/// String get lastName;
/// }
/// class NameMock extends TypedMock implements Name {
/// noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
/// }
class TypedMock {
final Map<Symbol, List<_InvocationMatcher>> _matchersMap = {};
@ -327,8 +361,11 @@ class TypedMock {
}
/// [ArgumentMatcher] checks whether the given argument satisfies some
/// condition.
abstract class ArgumentMatcher {
bool match(val);
/// Checks whether this matcher accepts the given argument.
bool matches(val);
}
@ -338,11 +375,12 @@ class _ArgumentMatcher_equals extends ArgumentMatcher {
_ArgumentMatcher_equals(this.expected);
@override
bool match(val) {
bool matches(val) {
return val == expected;
}
}
/// Matches an argument that is equal to the given [expected] value.
equals(expected) {
return new _ArgumentMatcher_equals(expected);
}
@ -350,39 +388,43 @@ equals(expected) {
class _ArgumentMatcher_anyBool extends ArgumentMatcher {
@override
bool match(val) {
bool matches(val) {
return val is bool;
}
}
/// Matches any [bool] value.
final anyBool = new _ArgumentMatcher_anyBool();
class _ArgumentMatcher_anyInt extends ArgumentMatcher {
@override
bool match(val) {
bool matches(val) {
return val is int;
}
}
/// Matches any [int] value.
final anyInt = new _ArgumentMatcher_anyInt();
class _ArgumentMatcher_anyObject extends ArgumentMatcher {
@override
bool match(val) {
bool matches(val) {
return true;
}
}
/// Matches any [Object] (or subclass) value.
final anyObject = new _ArgumentMatcher_anyObject();
class _ArgumentMatcher_anyString extends ArgumentMatcher {
@override
bool match(val) {
bool matches(val) {
return val is String;
}
}
/// Matches any [String] value.
final anyString = new _ArgumentMatcher_anyString();

View file

@ -0,0 +1,9 @@
name: typed_mock
version: 0.0.1
author: Dart Team <misc@dartlang.org>
description: A library for mocking classes using Mockito-like syntax
homepage: http://www.dartlang.org
environment:
sdk: '>=1.0.0 <2.0.0'
dev_dependencies:
unittest: '>=0.10.0 <0.12.0'

View file

@ -2,8 +2,8 @@ library test.typed_mock;
import 'package:unittest/unittest.dart';
import 'typed_mock.dart' hide equals;
import 'typed_mock.dart' as typed_mocks show equals;
import 'package:typed_mock/typed_mock.dart' hide equals;
import 'package:typed_mock/typed_mock.dart' as typed_mocks show equals;
abstract class TestInterface {
@ -37,39 +37,39 @@ main() {
group('Matchers', () {
test('equals', () {
expect(typed_mocks.equals(10).match(10), true);
expect(typed_mocks.equals(10).match(20), false);
expect(typed_mocks.equals('abc').match('abc'), true);
expect(typed_mocks.equals('abc').match('xyz'), false);
expect(typed_mocks.equals(10).matches(10), true);
expect(typed_mocks.equals(10).matches(20), false);
expect(typed_mocks.equals('abc').matches('abc'), true);
expect(typed_mocks.equals('abc').matches('xyz'), false);
});
test('anyBool', () {
expect(anyBool.match(true), true);
expect(anyBool.match(false), true);
expect(anyBool.match(0), false);
expect(anyBool.match('0'), false);
expect(anyBool.matches(true), true);
expect(anyBool.matches(false), true);
expect(anyBool.matches(0), false);
expect(anyBool.matches('0'), false);
});
test('anyInt', () {
expect(anyInt.match(true), false);
expect(anyInt.match(-99), true);
expect(anyInt.match(0), true);
expect(anyInt.match(42), true);
expect(anyInt.match('0'), false);
expect(anyInt.matches(true), false);
expect(anyInt.matches(-99), true);
expect(anyInt.matches(0), true);
expect(anyInt.matches(42), true);
expect(anyInt.matches('0'), false);
});
test('anyObject', () {
expect(anyObject.match(true), true);
expect(anyObject.match(0), true);
expect(anyObject.match('0'), true);
expect(anyObject.matches(true), true);
expect(anyObject.matches(0), true);
expect(anyObject.matches('0'), true);
});
test('anyString', () {
expect(anyString.match(true), false);
expect(anyString.match(0), false);
expect(anyString.match(''), true);
expect(anyString.match('0'), true);
expect(anyString.match('abc'), true);
expect(anyString.matches(true), false);
expect(anyString.matches(0), false);
expect(anyString.matches(''), true);
expect(anyString.matches('0'), true);
expect(anyString.matches('abc'), true);
});
});