bogus 0.0.3.rc.1 → 0.0.3.rc.2
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.
- data/Gemfile.lock +1 -1
- data/README.md +1 -1
- data/features/.nav +1 -0
- data/features/changelog.md +1 -0
- data/features/fakes/duck_types.feature +134 -0
- data/lib/bogus/class_methods.rb +22 -0
- data/lib/bogus/copies_classes.rb +3 -29
- data/lib/bogus/copies_methods.rb +31 -0
- data/lib/bogus/creates_fakes.rb +8 -2
- data/lib/bogus/double.rb +1 -1
- data/lib/bogus/has_overwritten_methods.rb +1 -0
- data/lib/bogus/injector.rb +8 -0
- data/lib/bogus/instance_methods.rb +22 -0
- data/lib/bogus/makes_ducks.rb +37 -0
- data/lib/bogus/makes_subtypes.rb +13 -0
- data/lib/bogus/mocking_dsl.rb +4 -0
- data/lib/bogus/public_methods.rb +10 -0
- data/lib/bogus/rspec_adapter.rb +1 -3
- data/lib/bogus/version.rb +1 -1
- data/spec/bogus/class_methods_spec.rb +44 -0
- data/spec/bogus/configuration_spec.rb +1 -1
- data/spec/bogus/copies_classes_spec.rb +1 -3
- data/spec/bogus/creates_fakes_spec.rb +20 -5
- data/spec/bogus/double_spec.rb +10 -0
- data/spec/bogus/instance_methods_spec.rb +45 -0
- data/spec/bogus/makes_ducks_spec.rb +87 -0
- data/spec/bogus/mocking_dsl_spec.rb +23 -1
- metadata +101 -96
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Bogus
|
2
2
|
|
3
3
|
[](http://travis-ci.org/psyho/bogus)
|
4
|
-
[](https://codeclimate.com/github/psyho/bogus)
|
5
5
|
|
6
6
|
## What is Bogus?
|
7
7
|
|
data/features/.nav
CHANGED
data/features/changelog.md
CHANGED
@@ -0,0 +1,134 @@
|
|
1
|
+
Feature: Faking duck types
|
2
|
+
|
3
|
+
Sometimes, your system contains more than one class that can satisfy a given role. Which of the possible implementations do you pick then, and how can you make sure that their interfaces stay in sync?
|
4
|
+
|
5
|
+
Bogus gives you a way of extracting the "lowest common interface" out of multiple classes. All you need to do is just pass the classes in question to the `make_duck` method:
|
6
|
+
|
7
|
+
make_duck(DatabaseLogger, NetworkLogger, DevNullLogger)
|
8
|
+
|
9
|
+
This call will return a new class, that contains only the methods that exist in the public interface of all of the given classes, and in all of them have the same signature.
|
10
|
+
|
11
|
+
To make things easier for you, Bogus will automatically make a duck type for you, every time you return multiple classes from fake:
|
12
|
+
|
13
|
+
fake(:logger) { [DatabaseLogger, NetworkLogger, DevNullLogger] }
|
14
|
+
|
15
|
+
It is of course also possible to do the same thing in the global fake configuration:
|
16
|
+
|
17
|
+
Bogus.fakes do
|
18
|
+
fake :logger, class: proc{
|
19
|
+
[DatabaseLogger, NetworkLogger, DevNullLogger]
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
Background:
|
24
|
+
Given a file named "foo.rb" with:
|
25
|
+
"""ruby
|
26
|
+
class DatabaseLogger
|
27
|
+
def error(message); end
|
28
|
+
def warn(message, level); end
|
29
|
+
def connection; end
|
30
|
+
end
|
31
|
+
|
32
|
+
class NetworkLogger
|
33
|
+
def error(message); end
|
34
|
+
def warn(message, level); end
|
35
|
+
def socket; end
|
36
|
+
end
|
37
|
+
|
38
|
+
class DevNullLogger
|
39
|
+
def error(message); end
|
40
|
+
def warn(message, level); end
|
41
|
+
def debug(message); end
|
42
|
+
end
|
43
|
+
|
44
|
+
class ExceptionNotifier
|
45
|
+
def initialize(logger)
|
46
|
+
@logger = logger
|
47
|
+
end
|
48
|
+
|
49
|
+
def notify(exception)
|
50
|
+
@logger.error(exception)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
"""
|
55
|
+
|
56
|
+
Scenario: Copying instance methods
|
57
|
+
Then spec file with following content should pass:
|
58
|
+
"""ruby
|
59
|
+
describe "make_duck" do
|
60
|
+
let(:duck) { make_duck(DatabaseLogger, NetworkLogger,
|
61
|
+
DevNullLogger) }
|
62
|
+
let(:duck_instance) { duck.new }
|
63
|
+
|
64
|
+
it "responds to error" do
|
65
|
+
duck_instance.should respond_to(:error)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "has arity 1 for error" do
|
69
|
+
duck_instance.method(:error).arity.should == 1
|
70
|
+
end
|
71
|
+
|
72
|
+
it "responds to warn" do
|
73
|
+
duck_instance.should respond_to(:warn)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "has arity 2 for warn" do
|
77
|
+
duck_instance.method(:warn).arity.should == 2
|
78
|
+
end
|
79
|
+
|
80
|
+
it "does not respond to connection" do
|
81
|
+
duck_instance.should_not respond_to(:connection)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "does not respond to socket" do
|
85
|
+
duck_instance.should_not respond_to(:socket)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "does not respond to debug" do
|
89
|
+
duck_instance.should_not respond_to(:debug)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
"""
|
93
|
+
|
94
|
+
Scenario: Faking duck types
|
95
|
+
Then spec file with following content should pass:
|
96
|
+
"""ruby
|
97
|
+
describe "fake with multiple classes" do
|
98
|
+
fake(:logger) { [DatabaseLogger,
|
99
|
+
NetworkLogger,
|
100
|
+
DevNullLogger] }
|
101
|
+
|
102
|
+
let(:notifier) { ExceptionNotifier.new(logger) }
|
103
|
+
|
104
|
+
it "logs the exception" do
|
105
|
+
notifier.notify("whoa!")
|
106
|
+
|
107
|
+
logger.should have_received.error("whoa!")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
"""
|
111
|
+
|
112
|
+
Scenario: Globally configured duck types
|
113
|
+
Then spec file with following content should pass:
|
114
|
+
"""ruby
|
115
|
+
Bogus.fakes do
|
116
|
+
logger_implementations = proc{ [DatabaseLogger,
|
117
|
+
NetworkLogger,
|
118
|
+
DevNullLogger] }
|
119
|
+
|
120
|
+
fake :logger, class: logger_implementations
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "fake with multiple classes" do
|
124
|
+
fake(:logger)
|
125
|
+
|
126
|
+
let(:notifier) { ExceptionNotifier.new(logger) }
|
127
|
+
|
128
|
+
it "logs the exception" do
|
129
|
+
notifier.notify("whoa!")
|
130
|
+
|
131
|
+
logger.should have_received.error("whoa!")
|
132
|
+
end
|
133
|
+
end
|
134
|
+
"""
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Bogus
|
2
|
+
class ClassMethods
|
3
|
+
extend Bogus::Takes
|
4
|
+
takes :klass
|
5
|
+
|
6
|
+
def all
|
7
|
+
klass.methods - Class.methods
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(name)
|
11
|
+
klass.method(name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def remove(name)
|
15
|
+
klass.instance_eval "undef #{name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def define(body)
|
19
|
+
klass.instance_eval(body)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/bogus/copies_classes.rb
CHANGED
@@ -2,39 +2,13 @@ module Bogus
|
|
2
2
|
class CopiesClasses
|
3
3
|
extend Takes
|
4
4
|
|
5
|
-
takes :
|
5
|
+
takes :copies_methods
|
6
6
|
|
7
7
|
def copy(klass)
|
8
8
|
copy_class = Class.new(Bogus::Fake)
|
9
|
-
|
10
9
|
copy_class.__copied_class__ = klass
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
return copy_class
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def copy_instance_methods(klass, copy_class)
|
20
|
-
instance_methods = klass.instance_methods - Object.instance_methods
|
21
|
-
|
22
|
-
instance_methods.each do |name|
|
23
|
-
copy_class.class_eval(method_as_string(klass.instance_method(name)))
|
24
|
-
end
|
10
|
+
copies_methods.copy(klass, copy_class)
|
11
|
+
copy_class
|
25
12
|
end
|
26
|
-
|
27
|
-
def copy_class_methods(klass, copy_class)
|
28
|
-
klass_methods = klass.methods - Class.methods
|
29
|
-
|
30
|
-
klass_methods.each do |name|
|
31
|
-
copy_class.instance_eval(method_as_string(klass.method(name)))
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def method_as_string(method)
|
36
|
-
makes_substitute_methods.stringify(method)
|
37
|
-
end
|
38
|
-
|
39
13
|
end
|
40
14
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Bogus
|
2
|
+
class CopiesMethods
|
3
|
+
extend Bogus::Takes
|
4
|
+
|
5
|
+
takes :makes_substitute_methods,
|
6
|
+
:instance_methods,
|
7
|
+
:class_methods
|
8
|
+
|
9
|
+
def copy(from, into)
|
10
|
+
copy_methods(from, into, instance_methods)
|
11
|
+
copy_methods(from, into, class_methods)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def copy_methods(original_class, copy_class, make_methods)
|
17
|
+
original_methods = make_methods.call(original_class)
|
18
|
+
copy_methods = make_methods.call(copy_class)
|
19
|
+
|
20
|
+
original_methods.all.each do |name|
|
21
|
+
method = original_methods.get(name)
|
22
|
+
body = method_as_string(method)
|
23
|
+
copy_methods.define(body)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_as_string(method)
|
28
|
+
makes_substitute_methods.stringify(method)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/bogus/creates_fakes.rb
CHANGED
@@ -4,11 +4,12 @@ module Bogus
|
|
4
4
|
|
5
5
|
extend Takes
|
6
6
|
|
7
|
-
takes :copies_classes, :converts_name_to_class
|
7
|
+
takes :copies_classes, :converts_name_to_class, :makes_ducks
|
8
8
|
|
9
9
|
def create(name, opts = {}, &block)
|
10
10
|
klass = self.klass(name, &block)
|
11
|
-
|
11
|
+
duck = make_duck(klass)
|
12
|
+
klass_copy = copies_classes.copy(duck)
|
12
13
|
|
13
14
|
mode = opts.fetch(:as, :instance)
|
14
15
|
|
@@ -28,5 +29,10 @@ module Bogus
|
|
28
29
|
return block.call if block_given?
|
29
30
|
converts_name_to_class.convert(name)
|
30
31
|
end
|
32
|
+
|
33
|
+
def make_duck(klass)
|
34
|
+
return klass unless klass.is_a?(Array)
|
35
|
+
makes_ducks.make(*klass)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
end
|
data/lib/bogus/double.rb
CHANGED
@@ -11,8 +11,8 @@ module Bogus
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def stubs(name, *args, &return_value)
|
14
|
-
double_tracker.track(object)
|
15
14
|
verifies_stub_definition.verify!(object, name, args)
|
15
|
+
double_tracker.track(object)
|
16
16
|
records_double_interactions.record(object, name, args, &return_value)
|
17
17
|
overwrites_methods.overwrite(object, name)
|
18
18
|
object.__shadow__.stubs(name, *args, &return_value)
|
data/lib/bogus/injector.rb
CHANGED
@@ -44,6 +44,14 @@ module Bogus
|
|
44
44
|
create_double(object).mock
|
45
45
|
end
|
46
46
|
|
47
|
+
def instance_methods(klass)
|
48
|
+
inject(InstanceMethods, klass: klass)
|
49
|
+
end
|
50
|
+
|
51
|
+
def class_methods(klass)
|
52
|
+
inject(ClassMethods, klass: klass)
|
53
|
+
end
|
54
|
+
|
47
55
|
def have_received_matcher
|
48
56
|
inject(HaveReceivedMatcher)
|
49
57
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Bogus
|
2
|
+
class InstanceMethods
|
3
|
+
extend Bogus::Takes
|
4
|
+
takes :klass
|
5
|
+
|
6
|
+
def all
|
7
|
+
klass.instance_methods - Object.instance_methods
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(name)
|
11
|
+
klass.instance_method(name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def remove(name)
|
15
|
+
klass.send(:undef_method, name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def define(body)
|
19
|
+
klass.class_eval(body)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Bogus
|
2
|
+
class MakesDucks
|
3
|
+
extend Bogus::Takes
|
4
|
+
|
5
|
+
takes :class_methods, :instance_methods, :makes_subtypes
|
6
|
+
|
7
|
+
def make(klass, *classes)
|
8
|
+
duck = makes_subtypes.make(klass)
|
9
|
+
classes.each do |klass|
|
10
|
+
remove_methods(class_methods.call(duck),
|
11
|
+
class_methods.call(klass))
|
12
|
+
remove_methods(instance_methods.call(duck),
|
13
|
+
instance_methods.call(klass))
|
14
|
+
end
|
15
|
+
duck
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def remove_methods(duck_methods, klass_methods)
|
21
|
+
not_in_klass = duck_methods.all - klass_methods.all
|
22
|
+
not_in_klass.each { |name| duck_methods.remove(name) }
|
23
|
+
|
24
|
+
duck_methods.all.each do |name|
|
25
|
+
duck_method = duck_methods.get(name)
|
26
|
+
klass_method = klass_methods.get(name)
|
27
|
+
unless same_interface?(duck_method, klass_method)
|
28
|
+
duck_methods.remove(name)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def same_interface?(method1, method2)
|
34
|
+
method1.parameters == method2.parameters
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/bogus/mocking_dsl.rb
CHANGED
data/lib/bogus/public_methods.rb
CHANGED
@@ -17,6 +17,7 @@ module Bogus
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def reset!
|
20
|
+
clear
|
20
21
|
@injector = Bogus::Injector.new
|
21
22
|
end
|
22
23
|
|
@@ -28,6 +29,10 @@ module Bogus
|
|
28
29
|
inject.create_mock(*args)
|
29
30
|
end
|
30
31
|
|
32
|
+
def make_duck(*args)
|
33
|
+
inject.makes_ducks.make(*args)
|
34
|
+
end
|
35
|
+
|
31
36
|
def have_received(*args)
|
32
37
|
inject.have_received_matcher(*args).method_call
|
33
38
|
end
|
@@ -42,6 +47,11 @@ module Bogus
|
|
42
47
|
|
43
48
|
def after_each_test
|
44
49
|
ensure_all_expectations_satisfied!
|
50
|
+
ensure
|
51
|
+
clear
|
52
|
+
end
|
53
|
+
|
54
|
+
def clear
|
45
55
|
reset_stubbed_methods
|
46
56
|
clear_expectations
|
47
57
|
reset_overwritten_classes
|
data/lib/bogus/rspec_adapter.rb
CHANGED
data/lib/bogus/version.rb
CHANGED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Bogus
|
4
|
+
describe ClassMethods do
|
5
|
+
class SampleClass
|
6
|
+
def foo(bar)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.bar(bam)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.hello
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:class_methods) { ClassMethods.new(SampleClass) }
|
17
|
+
|
18
|
+
it "lists the instance methods" do
|
19
|
+
class_methods.all.should == [:bar, :hello]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the instance methods by name" do
|
23
|
+
class_methods.get(:bar).should ==
|
24
|
+
SampleClass.method(:bar)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "removes methods by name" do
|
28
|
+
class_methods.remove(:hello)
|
29
|
+
|
30
|
+
SampleClass.should_not respond_to(:hello)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "defines instance methods" do
|
34
|
+
class_methods.define <<-EOF
|
35
|
+
def greet(name)
|
36
|
+
return "Hello, " + name + "!"
|
37
|
+
end
|
38
|
+
EOF
|
39
|
+
|
40
|
+
SampleClass.greet("Joe").should == "Hello, Joe!"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -57,9 +57,7 @@ describe Bogus::CopiesClasses do
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
let(:
|
61
|
-
let(:makes_substitute_methods) { isolate(Bogus::MakesSubstituteMethods) }
|
62
|
-
let(:copies_classes) { isolate(Bogus::CopiesClasses) }
|
60
|
+
let(:copies_classes) { Bogus.inject.copies_classes }
|
63
61
|
let(:fake_class) { copies_classes.copy(klass) }
|
64
62
|
let(:fake) { fake_class.new }
|
65
63
|
|
@@ -1,11 +1,12 @@
|
|
1
1
|
require_relative '../spec_helper'
|
2
2
|
|
3
3
|
describe Bogus::CreatesFakes do
|
4
|
-
let(:fake_class) { stub
|
5
|
-
let(:fake_instance) { stub
|
6
|
-
let(:converts_name_to_class) { stub
|
7
|
-
let(:copies_classes) { stub
|
8
|
-
let(:
|
4
|
+
let(:fake_class) { stub }
|
5
|
+
let(:fake_instance) { stub }
|
6
|
+
let(:converts_name_to_class) { stub }
|
7
|
+
let(:copies_classes) { stub }
|
8
|
+
let(:makes_ducks) { stub }
|
9
|
+
let(:creates_fakes) { isolate(Bogus::CreatesFakes) }
|
9
10
|
|
10
11
|
module Foo
|
11
12
|
end
|
@@ -56,4 +57,18 @@ describe Bogus::CreatesFakes do
|
|
56
57
|
copies_classes.should_not have_received.convert
|
57
58
|
end
|
58
59
|
end
|
60
|
+
|
61
|
+
module FooBarDuck
|
62
|
+
end
|
63
|
+
|
64
|
+
context "with multiple classes" do
|
65
|
+
it "creates a duck type out of those classes and fakes it" do
|
66
|
+
stub(makes_ducks).make(Foo, Bar) { FooBarDuck }
|
67
|
+
stub(copies_classes).copy(FooBarDuck) { :the_fake }
|
68
|
+
|
69
|
+
fake = creates_fakes.create(:role, as: :class) { [Foo, Bar] }
|
70
|
+
|
71
|
+
fake.should == :the_fake
|
72
|
+
end
|
73
|
+
end
|
59
74
|
end
|
data/spec/bogus/double_spec.rb
CHANGED
@@ -9,6 +9,16 @@ module Bogus
|
|
9
9
|
double.stub.foo("a", "b") { "the result" }
|
10
10
|
end
|
11
11
|
|
12
|
+
it "does not track existence of the double if verify fails" do
|
13
|
+
stub(verifies_stub_definition).verify!(object, :foo, ["a", "b"]) { raise NameError }
|
14
|
+
|
15
|
+
expect {
|
16
|
+
double.stub.foo("a", "b") { "the result" }
|
17
|
+
}.to raise_error
|
18
|
+
|
19
|
+
double_tracker.should_not have_received.track(object)
|
20
|
+
end
|
21
|
+
|
12
22
|
it "verifies stub definition" do
|
13
23
|
mock(verifies_stub_definition).verify!(object, :foo, ["a", "b"])
|
14
24
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Bogus
|
4
|
+
describe InstanceMethods do
|
5
|
+
class SampleClass
|
6
|
+
def foo(bar)
|
7
|
+
end
|
8
|
+
|
9
|
+
def hello
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.bar(bam)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:instance_methods) { InstanceMethods.new(SampleClass) }
|
17
|
+
|
18
|
+
it "lists the instance methods" do
|
19
|
+
instance_methods.all.should == [:foo, :hello]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the instance methods by name" do
|
23
|
+
instance_methods.get(:foo).should ==
|
24
|
+
SampleClass.instance_method(:foo)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "removes methods by name" do
|
28
|
+
instance_methods.remove(:hello)
|
29
|
+
|
30
|
+
SampleClass.new.should_not respond_to(:hello)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "defines instance methods" do
|
34
|
+
instance_methods.define <<-EOF
|
35
|
+
def greet(name)
|
36
|
+
return "Hello, " + name + "!"
|
37
|
+
end
|
38
|
+
EOF
|
39
|
+
|
40
|
+
instance = SampleClass.new
|
41
|
+
|
42
|
+
instance.greet("Joe").should == "Hello, Joe!"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Bogus
|
4
|
+
describe MakesDucks do
|
5
|
+
class DatabaseLogger
|
6
|
+
def debug(message); end
|
7
|
+
def warn(*args); end
|
8
|
+
def error(message, another_arg); end
|
9
|
+
def log(opts = {}); end
|
10
|
+
|
11
|
+
def self.foo(x, y, z = 1); end
|
12
|
+
def self.bar(x, y); end
|
13
|
+
end
|
14
|
+
|
15
|
+
class NetworkLogger
|
16
|
+
def debug(message); end
|
17
|
+
def warn(*args); end
|
18
|
+
def error(message); end
|
19
|
+
def socket; end
|
20
|
+
|
21
|
+
def self.foo(x, y, z = 1); end
|
22
|
+
def self.bar(x, y, z); end
|
23
|
+
def self.baz; end
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:class_methods) do
|
27
|
+
lambda{ |klass| ClassMethods.new(klass) }
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:instance_methods) do
|
31
|
+
lambda{ |klass| InstanceMethods.new(klass) }
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:makes_ducks) { Bogus.inject.makes_ducks }
|
35
|
+
let(:duck) { makes_ducks.make(DatabaseLogger, NetworkLogger) }
|
36
|
+
|
37
|
+
describe "the returned class" do
|
38
|
+
subject { duck }
|
39
|
+
|
40
|
+
it { should respond_to(:foo) }
|
41
|
+
|
42
|
+
it "should have arity -3 for foo" do
|
43
|
+
duck.method(:foo).arity.should == -3
|
44
|
+
end
|
45
|
+
|
46
|
+
it { should_not respond_to(:bar) }
|
47
|
+
it { should_not respond_to(:baz) }
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "instances of the returned class" do
|
51
|
+
subject { duck.new }
|
52
|
+
|
53
|
+
it { should respond_to(:debug) }
|
54
|
+
it { should respond_to(:warn) }
|
55
|
+
it { should_not respond_to(:error) }
|
56
|
+
it { should_not respond_to(:socket) }
|
57
|
+
end
|
58
|
+
|
59
|
+
module AlwaysEnabled
|
60
|
+
def enabled?; true; end
|
61
|
+
extend self
|
62
|
+
end
|
63
|
+
|
64
|
+
module AlwaysDisabled
|
65
|
+
def enabled?; false; end
|
66
|
+
extend self
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with modules" do
|
70
|
+
let(:duck) { makes_ducks.make(AlwaysDisabled, AlwaysEnabled)}
|
71
|
+
|
72
|
+
let(:duck_instance) do
|
73
|
+
object = Object.new
|
74
|
+
object.extend duck
|
75
|
+
object
|
76
|
+
end
|
77
|
+
|
78
|
+
it "copies class methods" do
|
79
|
+
duck.should respond_to(:enabled?)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "copies instance methods" do
|
83
|
+
duck_instance.should respond_to(:enabled?)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -18,7 +18,7 @@ describe Bogus::MockingDSL do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
before do
|
21
|
-
Bogus.
|
21
|
+
Bogus.reset!
|
22
22
|
end
|
23
23
|
|
24
24
|
describe "#stub" do
|
@@ -165,6 +165,28 @@ describe Bogus::MockingDSL do
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
+
class ExampleForMockingOnConstants
|
169
|
+
def self.bar(foo)
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.baz
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it "clears expected interactions from constants" do
|
177
|
+
Mocker.mock(ExampleForMockingOnConstants).bar("foo")
|
178
|
+
|
179
|
+
expect {
|
180
|
+
Bogus.after_each_test
|
181
|
+
}.to raise_error(Bogus::NotAllExpectationsSatisfied)
|
182
|
+
|
183
|
+
Mocker.stub(ExampleForMockingOnConstants).baz
|
184
|
+
|
185
|
+
expect {
|
186
|
+
Bogus.after_each_test
|
187
|
+
}.not_to raise_error(Bogus::NotAllExpectationsSatisfied)
|
188
|
+
end
|
189
|
+
|
168
190
|
context "with fakes" do
|
169
191
|
it_behaves_like "mocking dsl" do
|
170
192
|
let(:baz) { fake }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bogus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.3.rc.
|
4
|
+
version: 0.0.3.rc.2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-04-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: dependor
|
16
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70101148931040 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,15 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.0.4
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ! '>='
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: 0.0.4
|
24
|
+
version_requirements: *70101148931040
|
30
25
|
- !ruby/object:Gem::Dependency
|
31
26
|
name: rake
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
27
|
+
requirement: &70101148930480 !ruby/object:Gem::Requirement
|
33
28
|
none: false
|
34
29
|
requirements:
|
35
30
|
- - ! '>='
|
@@ -37,15 +32,10 @@ dependencies:
|
|
37
32
|
version: '0'
|
38
33
|
type: :development
|
39
34
|
prerelease: false
|
40
|
-
version_requirements:
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '0'
|
35
|
+
version_requirements: *70101148930480
|
46
36
|
- !ruby/object:Gem::Dependency
|
47
37
|
name: rspec
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirement: &70101148930000 !ruby/object:Gem::Requirement
|
49
39
|
none: false
|
50
40
|
requirements:
|
51
41
|
- - ! '>='
|
@@ -53,15 +43,10 @@ dependencies:
|
|
53
43
|
version: '0'
|
54
44
|
type: :development
|
55
45
|
prerelease: false
|
56
|
-
version_requirements:
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ! '>='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
46
|
+
version_requirements: *70101148930000
|
62
47
|
- !ruby/object:Gem::Dependency
|
63
48
|
name: cucumber
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirement: &70101148929420 !ruby/object:Gem::Requirement
|
65
50
|
none: false
|
66
51
|
requirements:
|
67
52
|
- - ! '>='
|
@@ -69,15 +54,10 @@ dependencies:
|
|
69
54
|
version: '0'
|
70
55
|
type: :development
|
71
56
|
prerelease: false
|
72
|
-
version_requirements:
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ! '>='
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: '0'
|
57
|
+
version_requirements: *70101148929420
|
78
58
|
- !ruby/object:Gem::Dependency
|
79
59
|
name: aruba
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirement: &70101148928920 !ruby/object:Gem::Requirement
|
81
61
|
none: false
|
82
62
|
requirements:
|
83
63
|
- - ! '>='
|
@@ -85,15 +65,10 @@ dependencies:
|
|
85
65
|
version: '0'
|
86
66
|
type: :development
|
87
67
|
prerelease: false
|
88
|
-
version_requirements:
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- - ! '>='
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
version: '0'
|
68
|
+
version_requirements: *70101148928920
|
94
69
|
- !ruby/object:Gem::Dependency
|
95
70
|
name: guard
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirement: &70101148928480 !ruby/object:Gem::Requirement
|
97
72
|
none: false
|
98
73
|
requirements:
|
99
74
|
- - ! '>='
|
@@ -101,15 +76,10 @@ dependencies:
|
|
101
76
|
version: '0'
|
102
77
|
type: :development
|
103
78
|
prerelease: false
|
104
|
-
version_requirements:
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ! '>='
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '0'
|
79
|
+
version_requirements: *70101148928480
|
110
80
|
- !ruby/object:Gem::Dependency
|
111
81
|
name: guard-rspec
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
82
|
+
requirement: &70101148927700 !ruby/object:Gem::Requirement
|
113
83
|
none: false
|
114
84
|
requirements:
|
115
85
|
- - ! '>='
|
@@ -117,15 +87,10 @@ dependencies:
|
|
117
87
|
version: '0'
|
118
88
|
type: :development
|
119
89
|
prerelease: false
|
120
|
-
version_requirements:
|
121
|
-
none: false
|
122
|
-
requirements:
|
123
|
-
- - ! '>='
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '0'
|
90
|
+
version_requirements: *70101148927700
|
126
91
|
- !ruby/object:Gem::Dependency
|
127
92
|
name: guard-cucumber
|
128
|
-
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirement: &70101148927140 !ruby/object:Gem::Requirement
|
129
94
|
none: false
|
130
95
|
requirements:
|
131
96
|
- - ! '>='
|
@@ -133,15 +98,10 @@ dependencies:
|
|
133
98
|
version: '0'
|
134
99
|
type: :development
|
135
100
|
prerelease: false
|
136
|
-
version_requirements:
|
137
|
-
none: false
|
138
|
-
requirements:
|
139
|
-
- - ! '>='
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
version: '0'
|
101
|
+
version_requirements: *70101148927140
|
142
102
|
- !ruby/object:Gem::Dependency
|
143
103
|
name: guard-ctags-bundler
|
144
|
-
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirement: &70101148942700 !ruby/object:Gem::Requirement
|
145
105
|
none: false
|
146
106
|
requirements:
|
147
107
|
- - ! '>='
|
@@ -149,15 +109,10 @@ dependencies:
|
|
149
109
|
version: '0'
|
150
110
|
type: :development
|
151
111
|
prerelease: false
|
152
|
-
version_requirements:
|
153
|
-
none: false
|
154
|
-
requirements:
|
155
|
-
- - ! '>='
|
156
|
-
- !ruby/object:Gem::Version
|
157
|
-
version: '0'
|
112
|
+
version_requirements: *70101148942700
|
158
113
|
- !ruby/object:Gem::Dependency
|
159
114
|
name: growl
|
160
|
-
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirement: &70101148942000 !ruby/object:Gem::Requirement
|
161
116
|
none: false
|
162
117
|
requirements:
|
163
118
|
- - ! '>='
|
@@ -165,15 +120,10 @@ dependencies:
|
|
165
120
|
version: '0'
|
166
121
|
type: :development
|
167
122
|
prerelease: false
|
168
|
-
version_requirements:
|
169
|
-
none: false
|
170
|
-
requirements:
|
171
|
-
- - ! '>='
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
version: '0'
|
123
|
+
version_requirements: *70101148942000
|
174
124
|
- !ruby/object:Gem::Dependency
|
175
125
|
name: libnotify
|
176
|
-
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirement: &70101148941300 !ruby/object:Gem::Requirement
|
177
127
|
none: false
|
178
128
|
requirements:
|
179
129
|
- - ! '>='
|
@@ -181,15 +131,10 @@ dependencies:
|
|
181
131
|
version: '0'
|
182
132
|
type: :development
|
183
133
|
prerelease: false
|
184
|
-
version_requirements:
|
185
|
-
none: false
|
186
|
-
requirements:
|
187
|
-
- - ! '>='
|
188
|
-
- !ruby/object:Gem::Version
|
189
|
-
version: '0'
|
134
|
+
version_requirements: *70101148941300
|
190
135
|
- !ruby/object:Gem::Dependency
|
191
136
|
name: rr
|
192
|
-
requirement: !ruby/object:Gem::Requirement
|
137
|
+
requirement: &70101148939560 !ruby/object:Gem::Requirement
|
193
138
|
none: false
|
194
139
|
requirements:
|
195
140
|
- - ! '>='
|
@@ -197,15 +142,10 @@ dependencies:
|
|
197
142
|
version: '0'
|
198
143
|
type: :development
|
199
144
|
prerelease: false
|
200
|
-
version_requirements:
|
201
|
-
none: false
|
202
|
-
requirements:
|
203
|
-
- - ! '>='
|
204
|
-
- !ruby/object:Gem::Version
|
205
|
-
version: '0'
|
145
|
+
version_requirements: *70101148939560
|
206
146
|
- !ruby/object:Gem::Dependency
|
207
147
|
name: relish
|
208
|
-
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirement: &70101148937800 !ruby/object:Gem::Requirement
|
209
149
|
none: false
|
210
150
|
requirements:
|
211
151
|
- - ! '>='
|
@@ -213,12 +153,7 @@ dependencies:
|
|
213
153
|
version: '0'
|
214
154
|
type: :development
|
215
155
|
prerelease: false
|
216
|
-
version_requirements:
|
217
|
-
none: false
|
218
|
-
requirements:
|
219
|
-
- - ! '>='
|
220
|
-
- !ruby/object:Gem::Version
|
221
|
-
version: '0'
|
156
|
+
version_requirements: *70101148937800
|
222
157
|
description: Decreases the need to write integration tests by ensuring that the things
|
223
158
|
you stub or mock actually exist.
|
224
159
|
email:
|
@@ -246,6 +181,7 @@ files:
|
|
246
181
|
- features/contract_tests/readme.md
|
247
182
|
- features/contract_tests/return_value_contracts.feature
|
248
183
|
- features/fakes/anonymous_doubles.feature
|
184
|
+
- features/fakes/duck_types.feature
|
249
185
|
- features/fakes/fake_objects.feature
|
250
186
|
- features/fakes/global_fake_configuration.feature
|
251
187
|
- features/fakes/readme.md
|
@@ -264,10 +200,12 @@ files:
|
|
264
200
|
- lib/bogus/adds_recording.rb
|
265
201
|
- lib/bogus/any_args.rb
|
266
202
|
- lib/bogus/anything.rb
|
203
|
+
- lib/bogus/class_methods.rb
|
267
204
|
- lib/bogus/configuration.rb
|
268
205
|
- lib/bogus/contract_not_fulfilled.rb
|
269
206
|
- lib/bogus/converts_name_to_class.rb
|
270
207
|
- lib/bogus/copies_classes.rb
|
208
|
+
- lib/bogus/copies_methods.rb
|
271
209
|
- lib/bogus/creates_fakes.rb
|
272
210
|
- lib/bogus/creates_fakes_with_stubbed_methods.rb
|
273
211
|
- lib/bogus/double.rb
|
@@ -279,10 +217,13 @@ files:
|
|
279
217
|
- lib/bogus/has_overwritten_methods.rb
|
280
218
|
- lib/bogus/have_received_matcher.rb
|
281
219
|
- lib/bogus/injector.rb
|
220
|
+
- lib/bogus/instance_methods.rb
|
282
221
|
- lib/bogus/interaction.rb
|
283
222
|
- lib/bogus/interaction_presenter.rb
|
284
223
|
- lib/bogus/interactions_repository.rb
|
224
|
+
- lib/bogus/makes_ducks.rb
|
285
225
|
- lib/bogus/makes_substitute_methods.rb
|
226
|
+
- lib/bogus/makes_subtypes.rb
|
286
227
|
- lib/bogus/method_stringifier.rb
|
287
228
|
- lib/bogus/mocking_dsl.rb
|
288
229
|
- lib/bogus/multi_stubber.rb
|
@@ -313,6 +254,7 @@ files:
|
|
313
254
|
- rbs.sh
|
314
255
|
- spec/bogus/adds_recording_spec.rb
|
315
256
|
- spec/bogus/anything_spec.rb
|
257
|
+
- spec/bogus/class_methods_spec.rb
|
316
258
|
- spec/bogus/configuration_spec.rb
|
317
259
|
- spec/bogus/converts_name_to_class_spec.rb
|
318
260
|
- spec/bogus/copies_classes_spec.rb
|
@@ -324,8 +266,10 @@ files:
|
|
324
266
|
- spec/bogus/fake_registry_spec.rb
|
325
267
|
- spec/bogus/fakes_classes_spec.rb
|
326
268
|
- spec/bogus/have_received_matcher_spec.rb
|
269
|
+
- spec/bogus/instance_methods_spec.rb
|
327
270
|
- spec/bogus/interaction_spec.rb
|
328
271
|
- spec/bogus/interactions_repository_spec.rb
|
272
|
+
- spec/bogus/makes_ducks_spec.rb
|
329
273
|
- spec/bogus/makes_substitute_methods_spec.rb
|
330
274
|
- spec/bogus/mocking_dsl_spec.rb
|
331
275
|
- spec/bogus/multi_stubber_spec.rb
|
@@ -359,7 +303,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
359
303
|
version: '0'
|
360
304
|
segments:
|
361
305
|
- 0
|
362
|
-
hash:
|
306
|
+
hash: 3986267174147275748
|
363
307
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
364
308
|
none: false
|
365
309
|
requirements:
|
@@ -368,8 +312,69 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
368
312
|
version: 1.3.1
|
369
313
|
requirements: []
|
370
314
|
rubyforge_project: bogus
|
371
|
-
rubygems_version: 1.8.
|
315
|
+
rubygems_version: 1.8.15
|
372
316
|
signing_key:
|
373
317
|
specification_version: 3
|
374
318
|
summary: Create fakes to make your isolated unit tests reliable.
|
375
|
-
test_files:
|
319
|
+
test_files:
|
320
|
+
- features/authors.md
|
321
|
+
- features/changelog.md
|
322
|
+
- features/configuration_options.feature
|
323
|
+
- features/contract_tests/contract_tests_mocks.feature
|
324
|
+
- features/contract_tests/contract_tests_spies.feature
|
325
|
+
- features/contract_tests/contract_tests_stubs.feature
|
326
|
+
- features/contract_tests/readme.md
|
327
|
+
- features/contract_tests/return_value_contracts.feature
|
328
|
+
- features/fakes/anonymous_doubles.feature
|
329
|
+
- features/fakes/duck_types.feature
|
330
|
+
- features/fakes/fake_objects.feature
|
331
|
+
- features/fakes/global_fake_configuration.feature
|
332
|
+
- features/fakes/readme.md
|
333
|
+
- features/fakes/replacing_classes.feature
|
334
|
+
- features/getting_started.md
|
335
|
+
- features/license.md
|
336
|
+
- features/readme.md
|
337
|
+
- features/safe_stubbing/argument_matchers.feature
|
338
|
+
- features/safe_stubbing/readme.md
|
339
|
+
- features/safe_stubbing/safe_mocking.feature
|
340
|
+
- features/safe_stubbing/safe_stubbing.feature
|
341
|
+
- features/safe_stubbing/spies.feature
|
342
|
+
- features/step_definitions/rspec_steps.rb
|
343
|
+
- features/support/env.rb
|
344
|
+
- spec/bogus/adds_recording_spec.rb
|
345
|
+
- spec/bogus/anything_spec.rb
|
346
|
+
- spec/bogus/class_methods_spec.rb
|
347
|
+
- spec/bogus/configuration_spec.rb
|
348
|
+
- spec/bogus/converts_name_to_class_spec.rb
|
349
|
+
- spec/bogus/copies_classes_spec.rb
|
350
|
+
- spec/bogus/creates_fakes_spec.rb
|
351
|
+
- spec/bogus/creates_fakes_with_stubbed_methods_spec.rb
|
352
|
+
- spec/bogus/double_spec.rb
|
353
|
+
- spec/bogus/ensures_all_interactions_satisfied_spec.rb
|
354
|
+
- spec/bogus/fake_configuration_spec.rb
|
355
|
+
- spec/bogus/fake_registry_spec.rb
|
356
|
+
- spec/bogus/fakes_classes_spec.rb
|
357
|
+
- spec/bogus/have_received_matcher_spec.rb
|
358
|
+
- spec/bogus/instance_methods_spec.rb
|
359
|
+
- spec/bogus/interaction_spec.rb
|
360
|
+
- spec/bogus/interactions_repository_spec.rb
|
361
|
+
- spec/bogus/makes_ducks_spec.rb
|
362
|
+
- spec/bogus/makes_substitute_methods_spec.rb
|
363
|
+
- spec/bogus/mocking_dsl_spec.rb
|
364
|
+
- spec/bogus/multi_stubber_spec.rb
|
365
|
+
- spec/bogus/overwriten_classes_spec.rb
|
366
|
+
- spec/bogus/overwrites_classes_spec.rb
|
367
|
+
- spec/bogus/overwrites_methods_spec.rb
|
368
|
+
- spec/bogus/proxy_class_spec.rb
|
369
|
+
- spec/bogus/record_interactions_spec.rb
|
370
|
+
- spec/bogus/records_double_interactions_spec.rb
|
371
|
+
- spec/bogus/registers_created_fakes_spec.rb
|
372
|
+
- spec/bogus/resets_overwritten_classes_spec.rb
|
373
|
+
- spec/bogus/resets_stubbed_methods_spec.rb
|
374
|
+
- spec/bogus/shadow_spec.rb
|
375
|
+
- spec/bogus/verifies_contracts_spec.rb
|
376
|
+
- spec/bogus/verifies_stub_definition_spec.rb
|
377
|
+
- spec/spec_helper.rb
|
378
|
+
- spec/support/fake_creator_of_fakes.rb
|
379
|
+
- spec/support/sample_fake.rb
|
380
|
+
- spec/tracks_existence_of_test_doubles_spec.rb
|