bogus 0.0.4 → 0.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 +7 -0
- data/Gemfile.lock +19 -1
- data/Guardfile +0 -7
- data/Guardfile.cucumber +9 -0
- data/README.md +42 -6
- data/bogus.gemspec +3 -0
- data/features/.nav +5 -2
- data/features/authors.md +10 -2
- data/features/changelog.md +11 -0
- data/features/configuration/fake_ar_attributes.feature +51 -0
- data/features/configuration/readme.md +7 -0
- data/features/{configuration_options.feature → configuration/search_modules.feature} +2 -2
- data/features/fakes/anonymous_doubles.feature +11 -7
- data/features/fakes/fake_objects.feature +0 -16
- data/lib/bogus/active_record_accessors.rb +41 -0
- data/lib/bogus/class_methods.rb +1 -1
- data/lib/bogus/configuration.rb +1 -0
- data/lib/bogus/constructor_methods.rb +18 -0
- data/lib/bogus/copies_methods.rb +7 -5
- data/lib/bogus/creates_fakes.rb +1 -1
- data/lib/bogus/creates_fakes_with_stubbed_methods.rb +1 -1
- data/lib/bogus/ensures_all_interactions_satisfied.rb +0 -2
- data/lib/bogus/fake.rb +8 -0
- data/lib/bogus/injector.rb +10 -0
- data/lib/bogus/instance_methods.rb +1 -1
- data/lib/bogus/interaction.rb +22 -3
- data/lib/bogus/interaction_presenter.rb +1 -1
- data/lib/bogus/makes_ducks.rb +5 -6
- data/lib/bogus/makes_subtypes.rb +1 -1
- data/lib/bogus/method_stringifier.rb +16 -8
- data/lib/bogus/record_interactions.rb +1 -1
- data/lib/bogus/records_double_interactions.rb +8 -7
- data/lib/bogus/registers_created_fakes.rb +10 -8
- data/lib/bogus/responds_to_everything.rb +8 -1
- data/lib/bogus/shadow.rb +3 -2
- data/lib/bogus/undefined_return_value.rb +11 -0
- data/lib/bogus/verifies_contracts.rb +12 -10
- data/lib/bogus/verifies_stub_definition.rb +37 -41
- data/lib/bogus/version.rb +1 -1
- data/spec/bogus/copies_classes_spec.rb +13 -6
- data/spec/bogus/creates_fakes_spec.rb +1 -1
- data/spec/bogus/fake_ar_attributes_spec.rb +72 -0
- data/spec/bogus/faking_factories_spec.rb +83 -0
- data/spec/bogus/frozen_fakes_spec.rb +59 -0
- data/spec/bogus/interaction_spec.rb +4 -0
- data/spec/bogus/method_copiers_spec.rb +26 -0
- data/spec/bogus/mocking_dsl_spec.rb +7 -3
- data/spec/bogus/overwrites_methods_spec.rb +2 -2
- data/spec/bogus/record_interactions_spec.rb +1 -1
- data/spec/bogus/ruby_2_support_spec.rb +96 -0
- data/spec/bogus/shadow_spec.rb +10 -8
- data/spec/bogus/verifies_stub_definition_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/support/matchers.rb +3 -0
- metadata +76 -66
@@ -0,0 +1,18 @@
|
|
1
|
+
module Bogus
|
2
|
+
class CopiesConstructor
|
3
|
+
extend Takes
|
4
|
+
takes :method_stringifier, :instance_methods, :class_methods
|
5
|
+
|
6
|
+
def copy(from, into)
|
7
|
+
return unless from.is_a?(Class)
|
8
|
+
initializer = instance_methods.call(from).get(:initialize)
|
9
|
+
body = body(initializer)
|
10
|
+
class_methods.call(into).define(body)
|
11
|
+
end
|
12
|
+
|
13
|
+
def body(initializer)
|
14
|
+
body = method_stringifier.stringify(initializer, "super")
|
15
|
+
body.gsub("initialize", "new")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/bogus/copies_methods.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
module Bogus
|
2
2
|
class CopiesMethods
|
3
|
-
extend
|
3
|
+
extend Takes
|
4
4
|
|
5
5
|
takes :makes_substitute_methods,
|
6
|
-
:
|
7
|
-
:
|
6
|
+
:method_copiers,
|
7
|
+
:copies_constructor
|
8
8
|
|
9
9
|
def copy(from, into)
|
10
|
-
|
11
|
-
|
10
|
+
method_copiers.each do |copier|
|
11
|
+
copy_methods(from, into, copier)
|
12
|
+
end
|
13
|
+
copies_constructor.copy(from, into)
|
12
14
|
end
|
13
15
|
|
14
16
|
private
|
data/lib/bogus/creates_fakes.rb
CHANGED
data/lib/bogus/fake.rb
CHANGED
@@ -10,6 +10,7 @@ module Bogus
|
|
10
10
|
extend FakeObject
|
11
11
|
|
12
12
|
def initialize(*args)
|
13
|
+
__shadow__
|
13
14
|
end
|
14
15
|
|
15
16
|
def to_s
|
@@ -27,6 +28,13 @@ module Bogus
|
|
27
28
|
class << self
|
28
29
|
attr_accessor :__copied_class__
|
29
30
|
|
31
|
+
alias :__create__ :new
|
32
|
+
|
33
|
+
def new(*args, &block)
|
34
|
+
__record__(:new, *args, &block)
|
35
|
+
__create__
|
36
|
+
end
|
37
|
+
|
30
38
|
def name
|
31
39
|
__copied_class__.name
|
32
40
|
end
|
data/lib/bogus/injector.rb
CHANGED
@@ -44,6 +44,16 @@ module Bogus
|
|
44
44
|
inject(ClassMethods, klass: klass)
|
45
45
|
end
|
46
46
|
|
47
|
+
def active_record_accessors(klass)
|
48
|
+
inject(ActiveRecordAccessors, klass: klass)
|
49
|
+
end
|
50
|
+
|
51
|
+
def method_copiers
|
52
|
+
copiers = [method(:class_methods), method(:instance_methods)]
|
53
|
+
copiers << method(:active_record_accessors) if configuration.fake_ar_attributes
|
54
|
+
copiers
|
55
|
+
end
|
56
|
+
|
47
57
|
def have_received_matcher
|
48
58
|
inject(HaveReceivedMatcher)
|
49
59
|
end
|
data/lib/bogus/interaction.rb
CHANGED
@@ -19,15 +19,26 @@ module Bogus
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def args
|
22
|
-
super.
|
22
|
+
args = super.map { |arg| remove_default_values_from_hash(arg) }
|
23
|
+
args.reject { |arg| arg.eql?(DefaultValue) }
|
23
24
|
end
|
24
25
|
|
25
26
|
private
|
26
27
|
|
27
28
|
def same_args?(other)
|
28
29
|
return true if any_args? || other.any_args?
|
29
|
-
|
30
|
-
args
|
30
|
+
|
31
|
+
other_args = normalize_other_args(args, other.args)
|
32
|
+
return false unless args.size == other_args.size
|
33
|
+
args.zip(other_args).all?{|a1, a2| a1 == a2 || a2 == a1}
|
34
|
+
end
|
35
|
+
|
36
|
+
def normalize_other_args(args, other_args)
|
37
|
+
if args.last.is_a?(Hash) && !other_args.last.is_a?(Hash)
|
38
|
+
other_args + [{}]
|
39
|
+
else
|
40
|
+
other_args
|
41
|
+
end
|
31
42
|
end
|
32
43
|
|
33
44
|
def same_result?(other)
|
@@ -40,5 +51,13 @@ module Bogus
|
|
40
51
|
rescue => e
|
41
52
|
self.error = e.class
|
42
53
|
end
|
54
|
+
|
55
|
+
def remove_default_values_from_hash(arg)
|
56
|
+
if arg.is_a?(Hash)
|
57
|
+
arg.reject { |_, val| val.eql?(DefaultValue) }
|
58
|
+
else
|
59
|
+
arg
|
60
|
+
end
|
61
|
+
end
|
43
62
|
end
|
44
63
|
end
|
data/lib/bogus/makes_ducks.rb
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
module Bogus
|
2
2
|
class MakesDucks
|
3
|
-
extend
|
3
|
+
extend Takes
|
4
4
|
|
5
|
-
takes :
|
5
|
+
takes :method_copiers, :makes_subtypes
|
6
6
|
|
7
7
|
def make(first_class, *classes)
|
8
8
|
duck = makes_subtypes.make(first_class)
|
9
9
|
classes.each do |klass|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
instance_methods.call(klass))
|
10
|
+
method_copiers.each do |copier|
|
11
|
+
remove_methods(copier.call(duck), copier.call(klass))
|
12
|
+
end
|
14
13
|
end
|
15
14
|
duck
|
16
15
|
end
|
data/lib/bogus/makes_subtypes.rb
CHANGED
@@ -10,21 +10,29 @@ module Bogus
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def arguments_as_string(arguments)
|
13
|
-
arguments
|
14
|
-
arguments.map{|type, name| argument_to_string(name, type) }.compact.join(', ')
|
13
|
+
stringify_arguments(arguments, DefaultValue)
|
15
14
|
end
|
16
15
|
|
17
16
|
def argument_values(arguments)
|
18
|
-
|
17
|
+
stringify_arguments(arguments)
|
19
18
|
end
|
20
19
|
|
21
|
-
|
20
|
+
private
|
21
|
+
|
22
|
+
def stringify_arguments(arguments, default = nil)
|
23
|
+
fill_in_missing_names(arguments).map do |type, name|
|
24
|
+
argument_to_string(name, type, default)
|
25
|
+
end.join(', ')
|
26
|
+
end
|
27
|
+
|
28
|
+
def argument_to_string(name, type, default)
|
22
29
|
case type
|
23
30
|
when :block then "&#{name}"
|
24
|
-
when :key
|
25
|
-
when :opt
|
26
|
-
when :req
|
27
|
-
when :rest
|
31
|
+
when :key then default ? "#{name}: #{default}" : "#{name}: #{name}"
|
32
|
+
when :opt then default ? "#{name} = #{default}" : name
|
33
|
+
when :req then name
|
34
|
+
when :rest then "*#{name}"
|
35
|
+
when :keyrest then "**#{name}"
|
28
36
|
else raise "unknown argument type: #{type}"
|
29
37
|
end
|
30
38
|
end
|
@@ -1,11 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Bogus
|
2
|
+
class RecordsDoubleInteractions
|
3
|
+
extend Takes
|
3
4
|
|
4
|
-
|
5
|
+
takes :doubled_interactions, :fake_registry
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def record(object, method_name, args, &block)
|
8
|
+
fake_name = fake_registry.name(object)
|
9
|
+
doubled_interactions.record(fake_name, method_name, *args, &block) if fake_name
|
10
|
+
end
|
9
11
|
end
|
10
|
-
|
11
12
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Bogus
|
2
|
+
class RegistersCreatedFakes
|
3
|
+
extend Takes
|
3
4
|
|
4
|
-
|
5
|
+
takes :creates_fakes, :fake_registry, :double_tracker
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
def create(name, opts = {}, &block)
|
8
|
+
fake = creates_fakes.create(name, opts, &block)
|
9
|
+
fake_registry.store(name, fake)
|
10
|
+
double_tracker.track(fake)
|
11
|
+
fake
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,11 +1,18 @@
|
|
1
1
|
module Bogus
|
2
2
|
class RespondsToEverything
|
3
|
+
include FakeObject
|
4
|
+
include RecordInteractions
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
__shadow__
|
8
|
+
end
|
9
|
+
|
3
10
|
def respond_to?(method)
|
4
11
|
true
|
5
12
|
end
|
6
13
|
|
7
14
|
def method_missing(name, *args, &block)
|
8
|
-
|
15
|
+
__record__(name, *args, &block)
|
9
16
|
end
|
10
17
|
end
|
11
18
|
end
|
data/lib/bogus/shadow.rb
CHANGED
@@ -2,10 +2,10 @@ module Bogus
|
|
2
2
|
class Shadow
|
3
3
|
attr_reader :calls
|
4
4
|
|
5
|
-
def initialize
|
5
|
+
def initialize
|
6
6
|
@calls = []
|
7
7
|
@stubs = []
|
8
|
-
@defaults =
|
8
|
+
@defaults = {}
|
9
9
|
@required = Set.new
|
10
10
|
end
|
11
11
|
|
@@ -54,6 +54,7 @@ module Bogus
|
|
54
54
|
def return_value(interaction)
|
55
55
|
_, return_value = @stubs.reverse.find{|i, v| i == interaction}
|
56
56
|
return_value ||= @defaults[interaction.method]
|
57
|
+
return_value ||= proc{ UndefinedReturnValue.new(interaction) }
|
57
58
|
return_value.call
|
58
59
|
end
|
59
60
|
end
|
@@ -1,16 +1,18 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Bogus
|
2
|
+
class VerifiesContracts
|
3
|
+
extend Takes
|
3
4
|
|
4
|
-
|
5
|
+
takes :doubled_interactions, :real_interactions
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
def verify(fake_name)
|
8
|
+
missed = doubled_interactions.for_fake(fake_name).reject do |interaction|
|
9
|
+
real_interactions.recorded?(fake_name, interaction)
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
unless missed.empty?
|
13
|
+
actual = real_interactions.for_fake(fake_name)
|
14
|
+
raise Bogus::ContractNotFulfilled.new(fake_name, missed: missed, actual: actual)
|
15
|
+
end
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
@@ -1,43 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
def any_args?(args)
|
41
|
-
[Bogus::AnyArgs] == args
|
1
|
+
module Bogus
|
2
|
+
class VerifiesStubDefinition
|
3
|
+
extend Takes
|
4
|
+
|
5
|
+
takes :method_stringifier
|
6
|
+
|
7
|
+
def verify!(object, method_name, args)
|
8
|
+
stubbing_non_existent_method!(object, method_name) unless object.respond_to?(method_name)
|
9
|
+
return unless object.methods.include?(method_name)
|
10
|
+
return if any_args?(args)
|
11
|
+
method = object.method(method_name)
|
12
|
+
verify_call!(method, args)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def verify_call!(method, args)
|
18
|
+
object = Object.new
|
19
|
+
fake_method = method_stringifier.stringify(method, "")
|
20
|
+
object.instance_eval(fake_method)
|
21
|
+
object.send(method.name, *args)
|
22
|
+
rescue ArgumentError
|
23
|
+
wrong_arguments!(method, args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def wrong_arguments!(method, args)
|
27
|
+
args_string = method_stringifier.arguments_as_string(method.parameters)
|
28
|
+
raise ArgumentError, "tried to stub #{method.name}(#{args_string}) with arguments: #{args.map(&:inspect).join(",")}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def stubbing_non_existent_method!(object, method_name)
|
32
|
+
raise NameError, "#{object.inspect} does not respond to #{method_name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def any_args?(args)
|
36
|
+
[Bogus::AnyArgs] == args
|
37
|
+
end
|
42
38
|
end
|
43
39
|
end
|