aidmock 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ /.bundle/
2
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gem "rspec"
4
+ gem "jeweler"
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ gemcutter (0.6.1)
6
+ git (1.2.5)
7
+ jeweler (1.4.0)
8
+ gemcutter (>= 0.1.0)
9
+ git (>= 1.2.5)
10
+ rubyforge (>= 2.0.0)
11
+ json_pure (1.4.6)
12
+ rspec (2.3.0)
13
+ rspec-core (~> 2.3.0)
14
+ rspec-expectations (~> 2.3.0)
15
+ rspec-mocks (~> 2.3.0)
16
+ rspec-core (2.3.1)
17
+ rspec-expectations (2.3.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.3.0)
20
+ rubyforge (2.0.4)
21
+ json_pure (>= 1.1.7)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ jeweler
28
+ rspec
data/README.textile ADDED
@@ -0,0 +1,5 @@
1
+ h1. Aidmock
2
+
3
+ Hi, we are under development, but if you wanna know more about what this project is for, check our "motivation":https://github.com/wilkerlucio/aidmock/wiki/Motivation page.
4
+
5
+ We will have something usable for you in soon :)
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "aidmock"
8
+ gem.summary = %Q{Aidmock, safe mocking and interfacing for Ruby}
9
+ gem.description = %Q{Aidmock, safe mocking and interfacing for Ruby}
10
+ gem.email = "wilkerlucio@gmail.com"
11
+ gem.homepage = "http://github.com/wilkerlucio/aidmock"
12
+ gem.authors = ["Wilker Lucio"]
13
+ end
14
+ Jeweler::GemcutterTasks.new
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'spec'
22
+ test.pattern = 'spec/**/*_spec.rb'
23
+ test.verbose = true
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'spec'
30
+ test.pattern = 'spec/**/*_spec.rb'
31
+ test.verbose = true
32
+ end
33
+ rescue LoadError
34
+ task :rcov do
35
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
36
+ end
37
+ end
38
+
39
+ task :test => :check_dependencies
40
+
41
+ task :default => :test
42
+
43
+ require 'rake/rdoctask'
44
+ Rake::RDocTask.new do |rdoc|
45
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
+
47
+ rdoc.rdoc_dir = 'rdoc'
48
+ rdoc.title = "aidmock #{version}"
49
+ rdoc.rdoc_files.include('README*')
50
+ rdoc.rdoc_files.include('lib/**/*.rb')
51
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/aidmock.gemspec ADDED
@@ -0,0 +1,71 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{aidmock}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Wilker Lucio"]
12
+ s.date = %q{2011-01-10}
13
+ s.description = %q{Aidmock, safe mocking and interfacing for Ruby}
14
+ s.email = %q{wilkerlucio@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.textile"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "README.textile",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "aidmock.gemspec",
26
+ "examples/mock_spec.rb",
27
+ "lib/aidmock.rb",
28
+ "lib/aidmock/basic_object.rb",
29
+ "lib/aidmock/errors.rb",
30
+ "lib/aidmock/frameworks.rb",
31
+ "lib/aidmock/frameworks/rspec.rb",
32
+ "lib/aidmock/interface.rb",
33
+ "lib/aidmock/matchers.rb",
34
+ "lib/aidmock/method_descriptor.rb",
35
+ "lib/aidmock/sanity.rb",
36
+ "lib/aidmock/void_class.rb",
37
+ "spec/aidmock/frameworks/rspec_spec.rb",
38
+ "spec/aidmock/interface_spec.rb",
39
+ "spec/aidmock/matchers_spec.rb",
40
+ "spec/aidmock/method_descriptor_spec.rb",
41
+ "spec/aidmock/sanity_spec.rb",
42
+ "spec/aidmock_spec.rb",
43
+ "spec/spec_helper.rb"
44
+ ]
45
+ s.homepage = %q{http://github.com/wilkerlucio/aidmock}
46
+ s.rdoc_options = ["--charset=UTF-8"]
47
+ s.require_paths = ["lib"]
48
+ s.rubygems_version = %q{1.3.7}
49
+ s.summary = %q{Aidmock, safe mocking and interfacing for Ruby}
50
+ s.test_files = [
51
+ "spec/aidmock/frameworks/rspec_spec.rb",
52
+ "spec/aidmock/interface_spec.rb",
53
+ "spec/aidmock/matchers_spec.rb",
54
+ "spec/aidmock/method_descriptor_spec.rb",
55
+ "spec/aidmock/sanity_spec.rb",
56
+ "spec/aidmock_spec.rb",
57
+ "spec/spec_helper.rb",
58
+ "examples/mock_spec.rb"
59
+ ]
60
+
61
+ if s.respond_to? :specification_version then
62
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
63
+ s.specification_version = 3
64
+
65
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
66
+ else
67
+ end
68
+ else
69
+ end
70
+ end
71
+
@@ -0,0 +1,50 @@
1
+ $: << File.expand_path("../../lib", __FILE__)
2
+ require 'aidmock'
3
+
4
+ RSpec.configure do |config|
5
+ config.after :each do
6
+ Aidmock.verify
7
+ end
8
+ end
9
+
10
+ class Person
11
+ def self.something(hi)
12
+
13
+ end
14
+
15
+ def first_name
16
+ "first"
17
+ end
18
+
19
+ def last_name
20
+ "last"
21
+ end
22
+
23
+ def full_name
24
+ first_name + " " + last_name
25
+ end
26
+ end
27
+
28
+ Aidmock.interface Person do
29
+ class_method :something, String, String
30
+
31
+ method :first_name, String
32
+ method :last_name, String
33
+ method :full_name, String
34
+ end
35
+
36
+ Aidmock::Sanity.sanitize
37
+
38
+ describe Person do
39
+ before :each do
40
+ @person = Person.new
41
+ end
42
+
43
+ context ".first_name" do
44
+ it "should return some" do
45
+ @person.stub(:first_name).and_return("f")
46
+ @person.stub(:last_name).and_return("l")
47
+ @person.full_name.should == "f l"
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,25 @@
1
+ # Copyright (c) 2011 Wilker Lúcio
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Aidmock
22
+ class BasicObject
23
+ instance_methods.each { |m| undef_method m unless m =~ /^__/ }
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ module Aidmock
2
+ class Error < ::StandardError; end
3
+ class InvalidMockError < Error; end
4
+ class MethodInterfaceNotDefinedError < InvalidMockError; end
5
+ class MethodInterfaceReturnNotMatchError < InvalidMockError; end
6
+ class MethodInterfaceArgumentsNotMatchError < InvalidMockError; end
7
+ end
@@ -0,0 +1,158 @@
1
+ # Copyright (c) 2011 Wilker Lúcio
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Aidmock
22
+ module Frameworks
23
+ module RSpec
24
+ class << self
25
+ def mocks
26
+ mocks = []
27
+
28
+ ::RSpec::Mocks.space.send(:mocks).each do |moc|
29
+ proxy = moc.send(:__mock_proxy)
30
+ object = proxy.instance_variable_get(:@object)
31
+
32
+ proxy.send(:method_doubles).each do |double|
33
+ (double.expectations + double.stubs).each do |stub|
34
+ method = stub.sym
35
+ result = parse_double_result(stub)
36
+ arguments = parse_double_arguments(stub)
37
+
38
+ mocks << MockDescriptor.new(object, method, result, arguments)
39
+ end
40
+ end
41
+ end
42
+
43
+ mocks
44
+ end
45
+
46
+ protected
47
+
48
+ def parse_double_result(double)
49
+ block = double.instance_variable_get(:@return_block)
50
+
51
+ if block
52
+ result = call_result_block(block)
53
+ double.instance_variable_get(:@consecutive) ? result : [result]
54
+ else
55
+ []
56
+ end
57
+ end
58
+
59
+ def call_result_block(block)
60
+ arity = block.arity
61
+ params = (1..arity).map { VoidClass.new }
62
+
63
+ block.call(*params)
64
+ end
65
+
66
+ def parse_double_arguments(double)
67
+ args = double.instance_variable_get(:@args_expectation)
68
+ matchers = args.instance_variable_get(:@matchers)
69
+
70
+ (matchers || []).map do |matcher|
71
+ extract_matcher_value(matcher)
72
+ end
73
+ end
74
+
75
+ def extract_matcher_value(matcher)
76
+ kind = matcher.class.name[/.+:(.+)$/, 1]
77
+ extractor = find_extractor(kind)
78
+ extractor.call(matcher)
79
+ end
80
+
81
+ def register_extractor(name, &block)
82
+ @extractors ||= {}
83
+ @extractors[name] = block
84
+ end
85
+
86
+ def find_extractor(name)
87
+ extractor = @extractors[name]
88
+ raise "Can't find extractor for #{name}" unless extractor
89
+ extractor
90
+ end
91
+
92
+ def extract_value(value)
93
+ if value.class.name =~ /^RSpec::Mocks::ArgumentMatchers/
94
+ extract_matcher_value(value)
95
+ else
96
+ value
97
+ end
98
+ end
99
+ end
100
+
101
+ register_extractor "AnyArgMatcher" do |matcher|
102
+ nil
103
+ end
104
+
105
+ register_extractor "BooleanMatcher" do |matcher|
106
+ true
107
+ end
108
+
109
+ register_extractor "HashIncludingMatcher" do |matcher|
110
+ expected = matcher.instance_variable_get(:@expected)
111
+
112
+ expected.inject({}) do |acc, (key, value)|
113
+ acc[key] = extract_value(value)
114
+ acc
115
+ end
116
+ end
117
+
118
+ register_extractor "HashNotIncludingMatcher" do |matcher|
119
+ {}
120
+ end
121
+
122
+ register_extractor "DuckTypeMatcher" do |matcher|
123
+ methods = matcher.instance_variable_get(:@methods_to_respond_to)
124
+ object = Object.new
125
+ singleton = class << object; self; end
126
+ singleton.class_eval do
127
+ methods.each do |method|
128
+ define_method method do
129
+ nil
130
+ end
131
+ end
132
+ end
133
+
134
+ object
135
+ end
136
+
137
+ register_extractor "InstanceOf" do |matcher|
138
+ klass = matcher.instance_variable_get(:@klass)
139
+ klass.allocate
140
+ end
141
+
142
+ register_extractor "KindOf" do |matcher|
143
+ klass = matcher.instance_variable_get(:@klass)
144
+ klass.allocate
145
+ end
146
+
147
+ register_extractor "EqualityProxy" do |matcher|
148
+ given = matcher.instance_variable_get(:@given)
149
+
150
+ extract_value(given)
151
+ end
152
+
153
+ register_extractor "RegexpMatcher" do |matcher|
154
+ matcher.instance_variable_get(:@regexp).to_s
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,27 @@
1
+ # Copyright (c) 2011 Wilker Lúcio
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Aidmock
22
+ module Frameworks
23
+ autoload :RSpec, 'aidmock/frameworks/rspec'
24
+
25
+ MockDescriptor = Struct.new(:object, :method, :result, :arguments)
26
+ end
27
+ end
@@ -0,0 +1,57 @@
1
+ # Copyright (c) 2011 Wilker Lúcio
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Aidmock
22
+ class Interface
23
+ include Matchers
24
+
25
+ attr_reader :klass, :methods, :class_methods
26
+
27
+ def initialize(klass)
28
+ @klass = klass
29
+ @methods = []
30
+ @class_methods = []
31
+ end
32
+
33
+ def method(name, type, *arguments)
34
+ method = MethodDescriptor.new(name, type, *arguments)
35
+ @methods << method
36
+ method
37
+ end
38
+
39
+ def class_method(name, type, *arguments)
40
+ method = MethodDescriptor.new(name, type, *arguments)
41
+ method.class_method = true
42
+ @class_methods << method
43
+ method
44
+ end
45
+
46
+ def find_method(mock)
47
+ methods = mock.object.instance_of?(Class) ? @class_methods : @methods
48
+ methods.find do |method|
49
+ if method.name.instance_of? ::Regexp
50
+ method.name.match mock.method.to_s
51
+ else
52
+ method.name == mock.method
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,181 @@
1
+ # Copyright (c) 2011 Wilker Lúcio
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Aidmock
22
+ module Matchers
23
+ def self.create(value)
24
+ return AnyMatcher.new(*value) if value.instance_of? ::Array
25
+ return AnythingMatcher.new if value.nil?
26
+ return KindOfMatcher.new(value) if value.instance_of? ::Class
27
+ return DuckTypeMatcher.new(value) if value.instance_of? ::Symbol
28
+ return HashMatcher.new(value) if value.instance_of? ::Hash
29
+ return value if value.respond_to? :match?
30
+
31
+ raise "Can't create matcher for #{value.inspect}"
32
+ end
33
+
34
+ class AnyMatcher
35
+ def initialize(*matchers)
36
+ @matchers = matchers.map { |matcher| ::Aidmock::Matchers.create(matcher) }
37
+ end
38
+
39
+ def match?(object)
40
+ @matchers.any? { |matcher| matcher.match? object }
41
+ end
42
+ end
43
+
44
+ def any_of(*matchers)
45
+ AnyMatcher.new(*matchers)
46
+ end
47
+
48
+ class AnythingMatcher
49
+ def match?(object)
50
+ true
51
+ end
52
+ end
53
+
54
+ def anything
55
+ AnythingMatcher.new
56
+ end
57
+
58
+ class DuckTypeMatcher
59
+ def initialize(*methods)
60
+ @methods = methods
61
+ end
62
+
63
+ def match?(object)
64
+ return true if object.nil?
65
+ @methods.all? { |method| object.respond_to? method }
66
+ end
67
+ end
68
+
69
+ def respond_to(*methods)
70
+ DuckTypeMatcher.new(*methods)
71
+ end
72
+
73
+ class InstanceOfMatcher
74
+ def initialize(klass)
75
+ @klass = klass
76
+ end
77
+
78
+ def match?(object)
79
+ return true if object.nil?
80
+ object.instance_of? @klass
81
+ end
82
+ end
83
+
84
+ def instance_of(klass)
85
+ InstanceOfMatcher.new(klass)
86
+ end
87
+
88
+ class KindOfMatcher
89
+ def initialize(klass)
90
+ @klass = klass
91
+ end
92
+
93
+ def match?(object)
94
+ return true if object.nil?
95
+ object.kind_of? @klass
96
+ end
97
+ end
98
+
99
+ def kind_of(klass)
100
+ KindOfMatcher.new(klass)
101
+ end
102
+
103
+ class HashMatcher
104
+ def initialize(check_hash, strict = false)
105
+ @hash = {}
106
+ @strict = strict
107
+
108
+ check_hash.each do |key, value|
109
+ @hash[key] = ::Aidmock::Matchers.create(value)
110
+ end
111
+ end
112
+
113
+ def match?(object)
114
+ return true if object.nil?
115
+ return false unless object.kind_of? Hash
116
+
117
+ return false if @strict and (@hash.keys - object.keys).length != 0
118
+
119
+ object.each do |key, value|
120
+ return false unless @hash.has_key? key
121
+ return false unless @hash[key].match? value
122
+ end
123
+
124
+ true
125
+ end
126
+ end
127
+
128
+ def hash_including(hash, strict = false)
129
+ HashMatcher.new(hash, strict)
130
+ end
131
+
132
+ class NotNilArgMatcher
133
+ def initialize(matcher)
134
+ @matcher = ::Aidmock::Matchers.create(matcher)
135
+ end
136
+
137
+ def match?(object)
138
+ return false if object.nil?
139
+ @matcher.match? object
140
+ end
141
+ end
142
+
143
+ def not_nil(value)
144
+ NotNilArgMatcher.new(value)
145
+ end
146
+
147
+ alias_method :nn, :not_nil
148
+
149
+ class OptionalArgMatcher
150
+ def initialize(matcher)
151
+ @matcher = ::Aidmock::Matchers.create(matcher)
152
+ end
153
+
154
+ def match?(object)
155
+ @matcher.match? object
156
+ end
157
+ end
158
+
159
+ def optional(value)
160
+ OptionalArgMatcher.new(value)
161
+ end
162
+
163
+ alias_method :o, :optional
164
+
165
+ class SplatArgMatcher
166
+ def initialize(matcher = nil)
167
+ @matcher = ::Aidmock::Matchers.create(matcher)
168
+ end
169
+
170
+ def match?(values)
171
+ values.all? { |value| @matcher.match? value }
172
+ end
173
+ end
174
+
175
+ def splat(value)
176
+ SplatArgMatcher.new(value)
177
+ end
178
+
179
+ alias_method :s, :splat
180
+ end
181
+ end