surrogate 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,9 +17,32 @@ class Surrogate
17
17
  @mocks_loaded = bool
18
18
  end
19
19
  end
20
+
21
+ module Matchers
22
+ def have_been_told_to(expected)
23
+ HaveBeenToldTo.new expected
24
+ end
25
+
26
+ def have_been_asked_for_its(expected)
27
+ HaveBeenAskedForIts.new expected
28
+ end
29
+
30
+ def have_been_initialized_with(*initialization_args, &block)
31
+ HaveBeenInitializedWith.new *initialization_args, &block
32
+ end
33
+ end
20
34
  end
21
35
  end
22
36
 
37
+ require 'rspec/core'
23
38
  require 'surrogate'
24
- require 'surrogate/rspec/api_method_matchers'
25
- require 'surrogate/rspec/substitutability_matchers'
39
+ require 'surrogate/rspec/substitute_for'
40
+
41
+ require 'surrogate/rspec/have_been_asked_for_its'
42
+ require 'surrogate/rspec/have_been_initialized_with'
43
+ require 'surrogate/rspec/have_been_told_to'
44
+
45
+
46
+ RSpec.configure do |config|
47
+ config.include Surrogate::RSpec::Matchers
48
+ end
@@ -3,60 +3,53 @@ class Surrogate
3
3
  # Superclass for all types of values. Where a value is anything stored
4
4
  # in an instance variable on a surrogate, intended to be returned by an api method
5
5
  class Value
6
-
7
6
  # convert raw arguments into a value
8
7
  def self.factory(*args, &block)
9
8
  arg = args.first
10
- # if arg.kind_of? Exception
11
- # Raiseable.new arg
12
- # else
13
- # MethodQueue.new args
14
- # end
15
9
  if args.size > 1
16
10
  ValueQueue.new args
17
11
  elsif arg.kind_of? Exception
18
12
  Raisable.new arg
19
- elsif arg.kind_of? Value
13
+ elsif arg.kind_of? BaseValue
20
14
  arg
21
15
  else
22
- Value.new arg
16
+ BaseValue.new arg
23
17
  end
24
18
  end
25
19
 
26
- def initialize(value)
27
- @value = value
28
- end
29
-
30
- def value(hatchling, method_name)
31
- @value
32
- end
20
+ # === the current set of possible values ===
33
21
 
34
- def factory(*args, &block)
35
- self.class.factory(*args, &block)
36
- end
37
- end
38
- end
22
+ class BaseValue
23
+ def initialize(value)
24
+ @value = value
25
+ end
39
26
 
27
+ def value(method_name)
28
+ @value
29
+ end
40
30
 
41
- # the current set of possible values
31
+ def factory(*args, &block)
32
+ Value.factory(*args, &block)
33
+ end
34
+ end
42
35
 
43
- class Surrogate
44
- class Value
45
36
 
46
- class Raisable < Value
37
+ class Raisable < BaseValue
47
38
  def value(*)
48
39
  raise @value
49
40
  end
50
41
  end
51
42
 
52
43
 
53
- class ValueQueue < Value
54
- QueueEmpty = Class.new StandardError
44
+ class ValueQueue < BaseValue
45
+ QueueEmpty = Class.new SurrogateError
55
46
 
56
- def value(hatchling, method_name)
57
- factory(dequeue).value(hatchling, method_name)
58
- ensure
59
- hatchling.unset_ivar method_name if empty?
47
+ def value(method_name)
48
+ if empty?
49
+ raise QueueEmpty
50
+ else
51
+ factory(dequeue).value(method_name)
52
+ end
60
53
  end
61
54
 
62
55
  def queue
@@ -1,3 +1,3 @@
1
1
  class Surrogate
2
- VERSION = "0.4.3"
2
+ VERSION = "0.5.0"
3
3
  end
data/lib/surrogate.rb CHANGED
@@ -5,6 +5,7 @@ require 'surrogate/options'
5
5
  require 'surrogate/values'
6
6
  require 'surrogate/endower'
7
7
  require 'surrogate/api_comparer'
8
+ require 'surrogate/invocation'
8
9
 
9
10
  class Surrogate
10
11
  UnpreparedMethodError = Class.new StandardError
@@ -45,11 +45,11 @@ describe Surrogate do
45
45
  user_class.find(2).should == :user1
46
46
 
47
47
  # set a queue of default values
48
- user_class.will_find :user1, :user2, :user3 # set three overrides
49
- user_class.find(11).should == :user1 # first override
50
- user_class.find(22).should == :user2 # second override
51
- user_class.find(33).should == :user3 # third override
52
- user_class.find(44).should be_a_kind_of Mock::User # back to default block
48
+ user_class.will_find :user1, :user2, :user3 # set three overrides
49
+ user_class.find(11).should == :user1 # first override
50
+ user_class.find(22).should == :user2 # second override
51
+ user_class.find(33).should == :user3 # third override
52
+ expect { user_class.find 44 }.to raise_error # raise error when nothing left to find
53
53
  # might also be nice to provide a way to raise an error
54
54
 
55
55
  # tracking invocations
@@ -72,24 +72,13 @@ describe 'define' do
72
72
  instance.will_wink(1, 2, 3).should equal instance
73
73
  end
74
74
 
75
- context 'it creates a queue of things to find then returns to normal behaviour' do
76
- specify 'when there is no default block' do
77
- mock = mocked_class.new
78
- mock.will_wink :quickly, [:slowly]
79
- mock.wink.should == :quickly
80
- mock.wink.should == [:slowly]
81
- expect { mock.wink }.to raise_error Surrogate::UnpreparedMethodError
82
- end
83
-
84
- specify 'when there is a default block' do
85
- mocked_class = Surrogate.endow(Class.new)
86
- mocked_class.define(:connect) { :default }
87
- mock = mocked_class.new
88
- mock.will_connect 1, 2
89
- mock.connect.should == 1
90
- mock.connect.should == 2
91
- mock.connect.should == :default
92
- end
75
+ # Is there something useful the error could say?
76
+ it 'creates a queue of things to find and raises a QueueEmpty error if there are none left' do
77
+ mock = mocked_class.new
78
+ mock.will_wink :quickly, [:slowly]
79
+ mock.wink.should == :quickly
80
+ mock.wink.should == [:slowly]
81
+ expect { mock.wink }.to raise_error Surrogate::Value::ValueQueue::QueueEmpty
93
82
  end
94
83
  end
95
84
 
@@ -140,24 +129,13 @@ describe 'define' do
140
129
  instance.will_have_age(1,2,3).should equal instance
141
130
  end
142
131
 
143
- context 'it creates a queue of things to find then returns to normal behaviour' do
144
- specify 'when there is no default block' do
145
- mock = mocked_class.new
146
- mock.will_have_age 12, 34
147
- mock.age.should == 12
148
- mock.age.should == 34
149
- expect { mock.age }.to raise_error Surrogate::UnpreparedMethodError
150
- end
151
-
152
- specify 'when there is a default block' do
153
- mocked_class = Surrogate.endow(Class.new)
154
- mocked_class.define(:name) { 'default' }
155
- mock = mocked_class.new
156
- mock.will_have_name 'a', 'b'
157
- mock.name.should == 'a'
158
- mock.name.should == 'b'
159
- mock.name.should == 'default'
160
- end
132
+ # Is there something useful the error could say?
133
+ it 'creates a queue of things to find and raises a QueueEmpty error if there are none left' do
134
+ mock = mocked_class.new
135
+ mock.will_have_age 12, 34
136
+ mock.age.should == 12
137
+ mock.age.should == 34
138
+ expect { mock.age }.to raise_error Surrogate::Value::ValueQueue::QueueEmpty
161
139
  end
162
140
  end
163
141
  end
@@ -271,12 +249,11 @@ describe 'define' do
271
249
  mock = mocked_class.new
272
250
  mock.meth 1
273
251
  mock.meth 1, 2
274
- mock.meth [1, 2]
275
- mock.invocations(:meth).should == [
276
- [1],
277
- [1, 2],
278
- [[1, 2]],
279
- ]
252
+ mock.invocations(:meth).should == [Surrogate::Invocation.new([1]), Surrogate::Invocation.new([1, 2])]
253
+
254
+ val = 0
255
+ mock.meth(1, 2) { val = 3 }
256
+ expect { mock.invocations(:meth).last.block.call }.to change { val }.from(0).to(3)
280
257
  end
281
258
 
282
259
  it 'raises an error if asked about invocations for api methods it does not know' do
@@ -0,0 +1,129 @@
1
+ require 'spec_helper'
2
+
3
+ # these all need error messages
4
+ describe 'RSpec matchers', 'have_been_told_to(...).with { |block| }' do
5
+
6
+ let(:dir) { Surrogate.endow(Class.new) { define(:chdir) { nil }}}
7
+ let(:dir_path) { '/some/dir/path' }
8
+
9
+ it 'fails if no submitted_blocks were found' do
10
+ dir.should_not have_been_told_to(:chdir).with(dir_path) { |block|
11
+ block.before { raise 'this should not be executed' }
12
+ }
13
+
14
+ dir.chdir dir_path
15
+
16
+ dir.should_not have_been_told_to(:chdir).with(dir_path) { |block|
17
+ block.before { raise 'this should not be executed' }
18
+ }
19
+
20
+ dir.chdir(dir_path) { }
21
+ dir.should have_been_told_to(:chdir).with(dir_path) { }
22
+ end
23
+
24
+ it "fails if the arguments don't match, even if the block does" do
25
+ dir.chdir(dir_path) { }
26
+ dir.should_not have_been_told_to(:chdir).with(dir_path.reverse) { }
27
+ dir.should have_been_told_to(:chdir).with(dir_path) { }
28
+ end
29
+
30
+ it 'yields a test_block that can make assertions' do
31
+ dir.chdir(dir_path) { }
32
+ block_yielded = nil
33
+ dir.should have_been_told_to(:chdir).with(dir_path) { |block|
34
+ block_yielded = block
35
+ }
36
+ block_yielded.should be
37
+ end
38
+
39
+ describe 'the .returns assertion' do
40
+ it "passes if the submitted_block does return the value" do
41
+ dir.chdir(dir_path) { 1 }
42
+ dir.should_not have_been_told_to(:chdir).with(dir_path) { |block| block.returns 2 }
43
+ dir.should have_been_told_to(:chdir).with(dir_path) { |block| block.returns 1 }
44
+ end
45
+
46
+ specify "if given a block, it passes the return value to it for making assertions" do
47
+ dir.chdir(dir_path) { 1 }
48
+
49
+ dir.should_not have_been_told_to(:chdir).with(dir_path) { |block|
50
+ block.returns { |result| result.should == 2 }
51
+ }
52
+
53
+ dir.should have_been_told_to(:chdir).with(dir_path) { |block|
54
+ block.returns { |result| result.should == 1 }
55
+ }
56
+ end
57
+ end
58
+
59
+
60
+ let(:file) { Surrogate.endow(Class.new) { define(:write) { true }}}
61
+ let(:file_name) { 'some_file_name.ext' }
62
+ let(:file_body) { 'some file body' }
63
+
64
+ describe 'the .before and .after hooks' do
65
+ specify "take blocks which it will evaluate before/after invoking the submitted_block" do
66
+ dir.chdir(dir_path) { file.write file_name, file_body }
67
+ dir.should have_been_told_to(:chdir).with(dir_path) { |block|
68
+ block.before { file.should_not have_been_told_to :write }
69
+ block.after { file.should have_been_told_to :write }
70
+ }
71
+ end
72
+
73
+ example "multiple invocations wrong number of times" do
74
+ dir.chdir(dir_path) { file.write file_name, file_body }
75
+ dir.chdir(dir_path) { file.write file_name, file_body }
76
+ dir.should_not have_been_told_to(:chdir).times(1).with(dir_path) { |block|
77
+ block.before { file.should_not have_been_told_to :write }
78
+ block.after { file.should have_been_told_to :write }
79
+ }
80
+ end
81
+
82
+ example "multiple invocations correct number of times" do
83
+ dir.chdir(dir_path) { file.write file_name, file_body }
84
+ dir.chdir(dir_path) { file.write file_name, file_body }
85
+ dir.should have_been_told_to(:chdir).times(2).with(dir_path) { |block|
86
+ block.before { file.should_not have_been_told_to :write }
87
+ block.after { file.should have_been_told_to :write }
88
+ }
89
+ end
90
+ end
91
+
92
+ describe 'the .arity assertion' do
93
+ it "takes a number corresponding to the arity of the block" do
94
+ klass = Surrogate.endow(Class.new)
95
+ klass.define(:meth) { self }
96
+ klass.new.meth { |a| }.should have_been_told_to(:meth).with { |b| b.arity 1 }
97
+ klass.new.meth { |a,b| }.should have_been_told_to(:meth).with { |b| b.arity 2 }
98
+ klass.new.meth { |a,b,c| }.should have_been_told_to(:meth).with { |b| b.arity 3 }
99
+ klass.new.meth { |*a| }.should have_been_told_to(:meth).with { |b| b.arity -1 }
100
+ expect {
101
+ klass.new.meth { |a| }.should have_been_told_to(:meth).with { |b| b.arity 123 }
102
+ }.to raise_error RSpec::Expectations::ExpectationNotMetError
103
+ end
104
+ end
105
+
106
+ describe ".call_with" do
107
+ it 'allows the user to provide arguments' do
108
+ klass = Surrogate.endow(Class.new).define(:add) { self }
109
+ instance = klass.new
110
+ instance.add { |a, b, &c| a + b + c.call }
111
+ instance.should have_been_told_to(:add).with { |block|
112
+ block.call_with(1, 2) { 3 }
113
+ block.returns 6
114
+ }
115
+
116
+ instance = klass.new
117
+ i = 10
118
+ instance.add { |n, &b| i += n + b.call }
119
+ instance.should have_been_told_to(:add).with { |block|
120
+ block.call_with(3) { 4 }
121
+ block.after { i.should == 17 }
122
+ }
123
+ end
124
+ end
125
+
126
+ describe ".raising is like RSpec's raise_error interface" do
127
+ it { pending 'IDK what I want this to be like yet' }
128
+ end
129
+ end
@@ -1,34 +1,37 @@
1
1
  require 'spec_helper'
2
2
 
3
- messages_for = Surrogate::RSpec::MessagesFor
4
3
 
5
- describe messages_for, 'argument inspection' do
4
+ describe Surrogate::RSpec::AbstractFailureMessage::ArgsInspector, 'argument inspection' do
6
5
 
7
6
  describe 'individual argument inspection inspection' do
8
7
  it 'inspects non RSpec matchers as their default inspection' do
9
- messages_for.inspect_argument("1").should == '"1"'
10
- messages_for.inspect_argument(1).should == "1"
11
- messages_for.inspect_argument([/a/]).should == "[/a/]"
8
+ described_class.inspect_argument("1").should == '"1"'
9
+ described_class.inspect_argument(1).should == "1"
10
+ described_class.inspect_argument([/a/]).should == "[/a/]"
12
11
  end
13
12
 
14
13
  it 'inspects rspec matchers' do
15
- messages_for.inspect_argument(no_args).should == 'no args'
16
- messages_for.inspect_argument(hash_including abc: 123).should == 'hash_including(:abc=>123)'
14
+ described_class.inspect_argument(no_args).should == 'no args'
15
+ described_class.inspect_argument(hash_including abc: 123).should == 'hash_including(:abc=>123)'
17
16
  end
18
17
  end
19
18
 
20
19
 
21
20
  describe 'multiple argument inspection' do
21
+ def inspect_args(args)
22
+ described_class.inspect Surrogate::Invocation.new(args)
23
+ end
24
+
22
25
  it "wraps individual arguments in `'" do
23
- messages_for.inspect_arguments([/a/]).should == "`/a/'"
26
+ inspect_args([/a/]).should == "`/a/'"
24
27
  end
25
28
 
26
29
  it "joins arguments with commas" do
27
- messages_for.inspect_arguments(['x', no_args]).should == "`\"x\", no args'"
30
+ inspect_args(['x', no_args]).should == "`\"x\", no args'"
28
31
  end
29
32
 
30
33
  it 'returns no_args when the array is empty' do
31
- messages_for.inspect_arguments([]).should == "`no args'"
34
+ inspect_args([]).should == "`no args'"
32
35
  end
33
36
  end
34
37
  end
data/surrogate.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_runtime_dependency 'bindable_block', '= 0.0.4'
21
+ s.add_runtime_dependency 'bindable_block', '= 0.0.5.1'
22
22
 
23
23
  s.add_development_dependency "rspec", '~> 2.8.0' # TODO: Figure out how far back we can work with
24
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: surrogate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-05 00:00:00.000000000 Z
12
+ date: 2012-06-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bindable_block
16
- requirement: &70325486799660 !ruby/object:Gem::Requirement
16
+ requirement: &70339421986340 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - =
20
20
  - !ruby/object:Gem::Version
21
- version: 0.0.4
21
+ version: 0.0.5.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70325486799660
24
+ version_requirements: *70339421986340
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &70325486799160 !ruby/object:Gem::Requirement
27
+ requirement: &70339421985140 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: 2.8.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70325486799160
35
+ version_requirements: *70339421985140
36
36
  description: Framework to aid in handrolling mock/spy objects.
37
37
  email:
38
38
  - josh.cheek@gmail.com
@@ -50,14 +50,22 @@ files:
50
50
  - lib/surrogate/endower.rb
51
51
  - lib/surrogate/hatchery.rb
52
52
  - lib/surrogate/hatchling.rb
53
+ - lib/surrogate/invocation.rb
53
54
  - lib/surrogate/options.rb
54
55
  - lib/surrogate/rspec.rb
55
- - lib/surrogate/rspec/api_method_matchers.rb
56
- - lib/surrogate/rspec/substitutability_matchers.rb
56
+ - lib/surrogate/rspec/abstract_failure_message.rb
57
+ - lib/surrogate/rspec/have_been_asked_for_its.rb
58
+ - lib/surrogate/rspec/have_been_initialized_with.rb
59
+ - lib/surrogate/rspec/have_been_told_to.rb
60
+ - lib/surrogate/rspec/invocation_matcher.rb
61
+ - lib/surrogate/rspec/substitute_for.rb
62
+ - lib/surrogate/rspec/times_predicate.rb
63
+ - lib/surrogate/rspec/with_filter.rb
57
64
  - lib/surrogate/values.rb
58
65
  - lib/surrogate/version.rb
59
66
  - spec/acceptance_spec.rb
60
67
  - spec/defining_api_methods_spec.rb
68
+ - spec/rspec/block_support_spec.rb
61
69
  - spec/rspec/have_been_asked_for_its_spec.rb
62
70
  - spec/rspec/have_been_initialized_with_spec.rb
63
71
  - spec/rspec/have_been_told_to_spec.rb
@@ -94,6 +102,7 @@ summary: Framework to aid in handrolling mock/spy objects.
94
102
  test_files:
95
103
  - spec/acceptance_spec.rb
96
104
  - spec/defining_api_methods_spec.rb
105
+ - spec/rspec/block_support_spec.rb
97
106
  - spec/rspec/have_been_asked_for_its_spec.rb
98
107
  - spec/rspec/have_been_initialized_with_spec.rb
99
108
  - spec/rspec/have_been_told_to_spec.rb