interjectable 1.0.0 → 1.1.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.
- checksums.yaml +4 -4
- data/CHANGES.md +6 -0
- data/README.md +9 -6
- data/lib/interjectable/rspec.rb +43 -28
- data/lib/interjectable/version.rb +1 -1
- data/spec/interjectable/rspec_spec.rb +5 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf87a04b27e693b7dec66842c4c51ea738a7942e
|
4
|
+
data.tar.gz: 6c8fdb8852fa3fc8dea1bb3f17ae47dbab4d29b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbe3d00e061ff7b5a39ba5f49564ee58f7cd07b69b9f927b4f2bf766d7cef3656ea452ef5305bbb2c75c4f0280fb1785c190bd2836d8547098af91d378b454ad
|
7
|
+
data.tar.gz: 980a68ad0da41b00ad1d0663f049137d9984bcc0be716dd592bd985247396ef8f6fd0657d802fe683415785643433c7fe7993a805cac93fec08844a07ef9ac7b
|
data/CHANGES.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
# v1.1.0
|
4
|
+
|
5
|
+
- Add another RSpec helper `test_inject` to avoid needing a local variable for
|
6
|
+
the setter block to reference. Again, see the [README.md](README.md) for
|
7
|
+
usage.
|
8
|
+
|
3
9
|
# v1.0.0
|
4
10
|
|
5
11
|
- Calling `#inject` or `#inject_static` multiple times is now an error. Use
|
data/README.md
CHANGED
@@ -79,12 +79,12 @@ require "interjectable/rspec"
|
|
79
79
|
describe A do
|
80
80
|
describe "#read" do
|
81
81
|
before do
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
82
|
+
# You can use the block form of #test_inject to inject a fake object that references methods on a.
|
83
|
+
a.test_inject(:b) { FakeB.new(foo) }
|
84
|
+
|
85
|
+
# You can use the test_inject RSpec helper if you just want to inject an object that doesn't
|
86
|
+
# need to reference anything on a.
|
87
|
+
test_inject(described_class, :c, instance_double(C, boom: "goat"))
|
88
88
|
end
|
89
89
|
|
90
90
|
it "parses from its b, and foos from its c" do
|
@@ -93,6 +93,9 @@ describe A do
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
+
# Both Interjectable.test_inject and the RSpec test_inject helper will setup
|
97
|
+
# RSpec after hooks to cleanup any test_inject-ed dependencies after the
|
98
|
+
# context they are defined in.
|
96
99
|
it "doesn't pollute other tests" do
|
97
100
|
expect(subject.read).to eq(B.new.parse)
|
98
101
|
expect(subject.foo).to eq(C.new.boom)
|
data/lib/interjectable/rspec.rb
CHANGED
@@ -2,15 +2,17 @@
|
|
2
2
|
|
3
3
|
module Interjectable
|
4
4
|
module ClassMethods
|
5
|
+
BLANK = Object.new
|
6
|
+
|
5
7
|
class SuperclassInjectStatic < Struct.new(:klass, :dependency)
|
6
|
-
def override(setter)
|
8
|
+
def override(value, &setter)
|
7
9
|
cvar = "@@#{dependency}"
|
8
10
|
klass.remove_class_variable(cvar) if klass.class_variable_defined?(cvar)
|
9
11
|
klass.define_singleton_method(dependency) do
|
10
12
|
if class_variable_defined?(cvar)
|
11
13
|
class_variable_get(cvar)
|
12
14
|
else
|
13
|
-
class_variable_set(cvar, instance_eval(&setter))
|
15
|
+
class_variable_set(cvar, value != ::Interjectable::ClassMethods::BLANK ? value : instance_eval(&setter))
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
@@ -36,13 +38,13 @@ module Interjectable
|
|
36
38
|
end
|
37
39
|
|
38
40
|
class SuperclassInject < Struct.new(:klass, :dependency)
|
39
|
-
def override(setter)
|
41
|
+
def override(value, &setter)
|
40
42
|
ivar = "@#{dependency}"
|
41
43
|
klass.define_method(dependency) do
|
42
44
|
if instance_variable_defined?(ivar)
|
43
45
|
instance_variable_get(ivar)
|
44
46
|
else
|
45
|
-
instance_variable_set(ivar, instance_eval(&setter))
|
47
|
+
instance_variable_set(ivar, value != ::Interjectable::ClassMethods::BLANK ? value : instance_eval(&setter))
|
46
48
|
end
|
47
49
|
end
|
48
50
|
end
|
@@ -72,31 +74,36 @@ module Interjectable
|
|
72
74
|
end
|
73
75
|
rspec_example_group = setter.binding.receiver.class
|
74
76
|
|
77
|
+
ClassMethods.test_inject(rspec_example_group, self, dependency, BLANK, &setter)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.test_inject(rspec_example_group, target, dependency, value, &setter)
|
81
|
+
unless value || setter
|
82
|
+
raise ArgumentError, "missing value or setter for #{target}'s #{dependency.inspect}"
|
83
|
+
end
|
84
|
+
|
75
85
|
unless rspec_example_group < RSpec::Core::ExampleGroup
|
76
86
|
raise "#test_inject can only be called from an RSpec ExampleGroup (e.g.: it, before, after)"
|
77
87
|
end
|
78
88
|
|
79
|
-
injector = if singleton_methods(false).include?(dependency) # inject_static(dependency) on this class
|
80
|
-
InjectStatic.new(
|
81
|
-
elsif singleton_methods.include?(dependency) # inject_static(dependency) on a superclass of this class
|
82
|
-
SuperclassInjectStatic.new(
|
83
|
-
elsif instance_methods(false).include?(dependency) # inject(dependency) on this class
|
84
|
-
Inject.new(
|
85
|
-
elsif instance_methods.include?(dependency) # inject(dependency) on a superclass of this class
|
86
|
-
SuperclassInject.new(
|
89
|
+
injector = if target.singleton_methods(false).include?(dependency) # inject_static(dependency) on this class
|
90
|
+
InjectStatic.new(target, dependency)
|
91
|
+
elsif target.singleton_methods.include?(dependency) # inject_static(dependency) on a superclass of this class
|
92
|
+
SuperclassInjectStatic.new(target, dependency)
|
93
|
+
elsif target.instance_methods(false).include?(dependency) # inject(dependency) on this class
|
94
|
+
Inject.new(target, dependency)
|
95
|
+
elsif target.instance_methods.include?(dependency) # inject(dependency) on a superclass of this class
|
96
|
+
SuperclassInject.new(target, dependency)
|
87
97
|
else
|
88
98
|
raise ArgumentError, "tried to override a non-existent dependency: #{dependency.inspect}"
|
89
99
|
end
|
90
100
|
|
91
|
-
injector.override(setter)
|
92
101
|
|
93
|
-
|
102
|
+
injector.override(value, &setter)
|
94
103
|
|
95
|
-
|
96
|
-
# if dependency == :dependency && scope == :each
|
97
|
-
# puts "override: #{key.inspect} #{rspec_example_group}"
|
98
|
-
# end
|
104
|
+
scope = rspec_example_group.currently_executing_a_context_hook? ? :context : :each
|
99
105
|
|
106
|
+
key = [target, dependency, scope]
|
100
107
|
# If we already have a restore after(:each) hook for this class +
|
101
108
|
# dependency + scope, don't add another. To check if we already have an
|
102
109
|
# after(:each) hook, we look at all previous after(:each) hooks we've
|
@@ -107,21 +114,29 @@ module Interjectable
|
|
107
114
|
# for the same #test_inject call since those before hooks only run once,
|
108
115
|
# and therefore only setup a single after hook.
|
109
116
|
return if scope == :each && RESTORE_HOOKS[key].any? { |group| rspec_example_group <= group }
|
110
|
-
# if dependency == :dependency && scope == :each
|
111
|
-
# puts "adding new after=#{key.inspect} hooks=#{RESTORE_HOOKS[key]} group=#{rspec_example_group}"
|
112
|
-
# end
|
113
117
|
RESTORE_HOOKS[key] << rspec_example_group
|
114
118
|
|
115
|
-
# if dependency == :dependency && scope == :each
|
116
|
-
# puts RESTORE_HOOKS.select { |(_, d, s)| d == :dependency && s == :each }
|
117
|
-
# end
|
118
|
-
|
119
119
|
rspec_example_group.after(scope) do
|
120
|
-
# if dependency == :dependency && scope == :each
|
121
|
-
# puts "restore: #{key.inspect} #{rspec_example_group}"
|
122
|
-
# end
|
123
120
|
injector.restore
|
124
121
|
end
|
125
122
|
end
|
126
123
|
end
|
124
|
+
|
125
|
+
module RSpecHelper
|
126
|
+
def test_inject(target, dependency, value)
|
127
|
+
unless value
|
128
|
+
raise ArgumentError, "missing value for #{dependency.inspect}, correct usage: test_inject(my_thing, #{dependency.inspect}, FakeDependency.new)"
|
129
|
+
end
|
130
|
+
|
131
|
+
ClassMethods.test_inject(self.class, target, dependency, value)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
if defined?(RSpec)
|
137
|
+
RSpec.configure do |c|
|
138
|
+
c.include(Interjectable::RSpecHelper)
|
139
|
+
end
|
140
|
+
else
|
141
|
+
raise "RSpec helper was required but RSpec has not beed defined"
|
127
142
|
end
|
@@ -50,7 +50,7 @@ describe "RSpec test helper #test_inject" do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
before do
|
53
|
-
|
53
|
+
test_inject(Klass, :dependency, :another_unused_dependency)
|
54
54
|
Klass.test_inject(:dependency) { foo }
|
55
55
|
Klass.test_inject(:static_dependency) { :overriden_static_dependency }
|
56
56
|
end
|
@@ -75,7 +75,7 @@ describe "RSpec test helper #test_inject" do
|
|
75
75
|
context "override dependency" do
|
76
76
|
before(:all) do
|
77
77
|
Klass.test_inject(:dependency) { :yet_another_unused_dependency }
|
78
|
-
|
78
|
+
test_inject(Klass, :static_dependency, :unused_static_dependency)
|
79
79
|
end
|
80
80
|
|
81
81
|
before do
|
@@ -143,7 +143,8 @@ describe "RSpec test helper #test_inject" do
|
|
143
143
|
context "isoloated context: subclass before :all" do
|
144
144
|
before(:all) do
|
145
145
|
SubKlass.test_inject(:static_dependency) { :bar }
|
146
|
-
SubKlass.test_inject(:static_dependency) { :
|
146
|
+
SubKlass.test_inject(:static_dependency) { :zoo }
|
147
|
+
test_inject(SubKlass, :static_dependency, :baz)
|
147
148
|
end
|
148
149
|
|
149
150
|
it "sets the static_dependency" do
|
@@ -152,7 +153,7 @@ describe "RSpec test helper #test_inject" do
|
|
152
153
|
|
153
154
|
context "subcontext" do
|
154
155
|
before(:all) do
|
155
|
-
|
156
|
+
test_inject(SubKlass, :static_dependency, :goat)
|
156
157
|
end
|
157
158
|
|
158
159
|
it "sets the static_dependency" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: interjectable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zach Margolis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A simple dependency injection library for unit testing
|
14
14
|
email:
|