surrogate 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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