bogus 0.0.3.rc.1 → 0.0.3.rc.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![build status](https://secure.travis-ci.org/psyho/bogus.png)](http://travis-ci.org/psyho/bogus)
|
4
|
-
[![Code Climate](https://codeclimate.com/
|
4
|
+
[![Code Climate](https://codeclimate.com/github/psyho/bogus.png)](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
|