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.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile.lock +19 -1
  3. data/Guardfile +0 -7
  4. data/Guardfile.cucumber +9 -0
  5. data/README.md +42 -6
  6. data/bogus.gemspec +3 -0
  7. data/features/.nav +5 -2
  8. data/features/authors.md +10 -2
  9. data/features/changelog.md +11 -0
  10. data/features/configuration/fake_ar_attributes.feature +51 -0
  11. data/features/configuration/readme.md +7 -0
  12. data/features/{configuration_options.feature → configuration/search_modules.feature} +2 -2
  13. data/features/fakes/anonymous_doubles.feature +11 -7
  14. data/features/fakes/fake_objects.feature +0 -16
  15. data/lib/bogus/active_record_accessors.rb +41 -0
  16. data/lib/bogus/class_methods.rb +1 -1
  17. data/lib/bogus/configuration.rb +1 -0
  18. data/lib/bogus/constructor_methods.rb +18 -0
  19. data/lib/bogus/copies_methods.rb +7 -5
  20. data/lib/bogus/creates_fakes.rb +1 -1
  21. data/lib/bogus/creates_fakes_with_stubbed_methods.rb +1 -1
  22. data/lib/bogus/ensures_all_interactions_satisfied.rb +0 -2
  23. data/lib/bogus/fake.rb +8 -0
  24. data/lib/bogus/injector.rb +10 -0
  25. data/lib/bogus/instance_methods.rb +1 -1
  26. data/lib/bogus/interaction.rb +22 -3
  27. data/lib/bogus/interaction_presenter.rb +1 -1
  28. data/lib/bogus/makes_ducks.rb +5 -6
  29. data/lib/bogus/makes_subtypes.rb +1 -1
  30. data/lib/bogus/method_stringifier.rb +16 -8
  31. data/lib/bogus/record_interactions.rb +1 -1
  32. data/lib/bogus/records_double_interactions.rb +8 -7
  33. data/lib/bogus/registers_created_fakes.rb +10 -8
  34. data/lib/bogus/responds_to_everything.rb +8 -1
  35. data/lib/bogus/shadow.rb +3 -2
  36. data/lib/bogus/undefined_return_value.rb +11 -0
  37. data/lib/bogus/verifies_contracts.rb +12 -10
  38. data/lib/bogus/verifies_stub_definition.rb +37 -41
  39. data/lib/bogus/version.rb +1 -1
  40. data/spec/bogus/copies_classes_spec.rb +13 -6
  41. data/spec/bogus/creates_fakes_spec.rb +1 -1
  42. data/spec/bogus/fake_ar_attributes_spec.rb +72 -0
  43. data/spec/bogus/faking_factories_spec.rb +83 -0
  44. data/spec/bogus/frozen_fakes_spec.rb +59 -0
  45. data/spec/bogus/interaction_spec.rb +4 -0
  46. data/spec/bogus/method_copiers_spec.rb +26 -0
  47. data/spec/bogus/mocking_dsl_spec.rb +7 -3
  48. data/spec/bogus/overwrites_methods_spec.rb +2 -2
  49. data/spec/bogus/record_interactions_spec.rb +1 -1
  50. data/spec/bogus/ruby_2_support_spec.rb +96 -0
  51. data/spec/bogus/shadow_spec.rb +10 -8
  52. data/spec/bogus/verifies_stub_definition_spec.rb +1 -1
  53. data/spec/spec_helper.rb +1 -1
  54. data/spec/support/matchers.rb +3 -0
  55. metadata +76 -66
data/lib/bogus/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Bogus
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -51,10 +51,6 @@ describe Bogus::CopiesClasses do
51
51
  subject.baa('hello')
52
52
  subject.baa('hello') {}
53
53
  end
54
-
55
- it "makes the methods chainable" do
56
- subject.foo.bar('hello').baz('hello', 'world', 'foo').bam.baa('foo')
57
- end
58
54
  end
59
55
 
60
56
  let(:copies_classes) { Bogus.inject.copies_classes }
@@ -77,11 +73,22 @@ describe Bogus::CopiesClasses do
77
73
  Class.new do
78
74
  def initialize(hello)
79
75
  end
76
+
77
+ def foo
78
+ end
80
79
  end
81
80
  }
82
81
 
83
- it "adds a constructor that allows passing any number of arguments" do
84
- fake_class.new('hello', 'w', 'o', 'r', 'l', 'd') { test }
82
+ it "adds a no-arg constructor" do
83
+ instance = fake_class.__create__
84
+
85
+ instance.should respond_to(:foo)
86
+ end
87
+
88
+ it "adds a constructor that allows passing the correct number of arguments" do
89
+ instance = fake_class.new('hello')
90
+
91
+ instance.should respond_to(:foo)
85
92
  end
86
93
  end
87
94
 
@@ -14,7 +14,7 @@ describe Bogus::CreatesFakes do
14
14
  module Bar
15
15
  end
16
16
 
17
- before { stub(fake_class).new{fake_instance} }
17
+ before { stub(fake_class).__create__{fake_instance} }
18
18
 
19
19
  context "without block" do
20
20
  before do
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+ require 'active_record'
3
+ require 'nulldb'
4
+
5
+ describe "Stubbing ActiveRecord::Base subclasses" do
6
+ ActiveRecord::Schema.verbose = false
7
+ ActiveRecord::Base.establish_connection :adapter => :nulldb
8
+
9
+ ActiveRecord::Schema.define do
10
+ create_table :blog_posts do |t|
11
+ t.string :name
12
+ t.string :author
13
+ end
14
+ end
15
+
16
+ class BlogPost < ActiveRecord::Base
17
+ def author(x)
18
+ "#{x} #{self[:author]}!"
19
+ end
20
+ end
21
+
22
+ include Bogus::MockingDSL
23
+
24
+ before do
25
+ Bogus.configure do |c|
26
+ c.fake_ar_attributes = true
27
+ end
28
+ end
29
+
30
+ it "makes it possible to stub active record fields" do
31
+ post = fake(:blog_post, name: "hello")
32
+
33
+ post.name.should == "hello"
34
+ end
35
+
36
+ it "works only when enabled in configuration" do
37
+ Bogus.configure do |c|
38
+ c.fake_ar_attributes = false
39
+ end
40
+
41
+ expect {
42
+ fake(:blog_post, name: "hello")
43
+ }.to raise_error(NameError)
44
+ end
45
+
46
+ it "does not overwrite existing method signatures" do
47
+ post = fake(:blog_post)
48
+
49
+ post.author("hello")
50
+
51
+ post.should have_received.author("hello")
52
+ end
53
+
54
+ class ExampleForActiveRecordAttributes
55
+ def foo(x)
56
+ end
57
+ end
58
+
59
+ it "does not interfere with non-ar classes" do
60
+ fake = fake(:example_for_active_record_attributes)
61
+
62
+ fake.foo(1)
63
+
64
+ fake.should have_received.foo(1)
65
+ end
66
+
67
+ after do
68
+ Bogus.configure do |c|
69
+ c.fake_ar_attributes = false
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Faking Factories" do
4
+ include Bogus::MockingDSL
5
+
6
+ class ExampleFactory
7
+ def initialize(model_class)
8
+ @model_class = model_class
9
+ end
10
+
11
+ def create(y)
12
+ @model_class.new(1, y)
13
+ end
14
+ end
15
+
16
+ class ExampleModel1
17
+ def initialize(x, y)
18
+ end
19
+ end
20
+
21
+ it "allows spying on factory classes" do
22
+ model_class = fake(:example_model, as: :class) { ExampleModel1 }
23
+ factory = ExampleFactory.new(model_class)
24
+
25
+ factory.create(2)
26
+
27
+ model_class.should have_received.new(1, 2)
28
+ end
29
+
30
+ class ExampleModel2
31
+ def initialize(x, y, z)
32
+ end
33
+ end
34
+
35
+ it "retains the arity safety" do
36
+ model_class = fake(:example_model, as: :class) { ExampleModel2 }
37
+ factory = ExampleFactory.new(model_class)
38
+
39
+ expect {
40
+ factory.create(2)
41
+ }.to raise_error(ArgumentError)
42
+ end
43
+
44
+ class ExampleModel3
45
+ end
46
+
47
+ it "works with classes with no explicit constructor" do
48
+ model_class = fake(:example_model, as: :class) { ExampleModel3 }
49
+
50
+ model = model_class.new
51
+
52
+ model_class.should have_received.new
53
+ end
54
+
55
+ class ExampleModel4
56
+ def initialize(y)
57
+ end
58
+
59
+ def foo(x)
60
+ end
61
+ end
62
+
63
+ it "allows creating the model instances as usual" do
64
+ model = fake(:example_model) { ExampleModel4 }
65
+
66
+ model.foo(1)
67
+
68
+ model.should have_received.foo(1)
69
+ end
70
+
71
+ module ExampleModel5
72
+ def self.foo(x)
73
+ end
74
+ end
75
+
76
+ it "allows creating fakes of modules as usual" do
77
+ model = fake(:example_model, as: :class) { ExampleModel5 }
78
+
79
+ model.foo(1)
80
+
81
+ model.should have_received.foo(1)
82
+ end
83
+ end
@@ -0,0 +1,59 @@
1
+ require "spec_helper"
2
+
3
+ describe "Frozen Fakes" do
4
+ include Bogus::MockingDSL
5
+
6
+ class ExampleForFreezing
7
+ def foo(x)
8
+ end
9
+ end
10
+
11
+ shared_examples_for "frozen fakes" do
12
+ before { object.freeze }
13
+
14
+ describe "stubbing" do
15
+ it "allows stubbing" do
16
+ stub(object).foo(1) { 123 }
17
+
18
+ object.foo(1).should == 123
19
+ end
20
+ end
21
+
22
+ describe "mocking" do
23
+ it "allows mocking" do
24
+ mock(object).foo(1) { 123 }
25
+
26
+ object.foo(1).should == 123
27
+ end
28
+
29
+ it "allows verifying expectations" do
30
+ mock(object).foo(1) { 123 }
31
+
32
+ expect {
33
+ Bogus.after_each_test
34
+ }.to raise_error(Bogus::NotAllExpectationsSatisfied)
35
+ end
36
+ end
37
+
38
+ describe "spying" do
39
+ it "allows spying" do
40
+ object.foo(1)
41
+
42
+ object.should have_received.foo(1)
43
+ object.should_not have_received.foo(2)
44
+ end
45
+ end
46
+ end
47
+
48
+ context "anonymous fakes" do
49
+ let(:object) { fake }
50
+
51
+ include_examples "frozen fakes"
52
+ end
53
+
54
+ context "named fakes" do
55
+ let(:object) { fake(:example_for_freezing) }
56
+
57
+ include_examples "frozen fakes"
58
+ end
59
+ end
@@ -6,6 +6,9 @@ describe Bogus::Interaction do
6
6
  same = [
7
7
  [[:foo, [:bar], "value"], [:foo, [:bar], "value"]],
8
8
  [[:foo, [:bar, Bogus::DefaultValue], "value"], [:foo, [:bar], "value"]],
9
+ [[:foo, [:bar, {foo: Bogus::DefaultValue}], "value"], [:foo, [:bar], "value"]],
10
+ [[:foo, [:bar, {foo: Bogus::DefaultValue}], "value"], [:foo, [:bar, {}], "value"]],
11
+ [[:foo, [:bar, {foo: Bogus::DefaultValue, bar: 1}], "value"], [:foo, [:bar, {bar: 1}], "value"]],
9
12
  [[:foo, [:bar]], [:foo, [:bar], "value"]],
10
13
  [[:foo, [:bar], "value"], [:foo, [:bar]]],
11
14
  [[:foo, [:bar]], [:foo, [:bar]]],
@@ -23,6 +26,7 @@ describe Bogus::Interaction do
23
26
  [[:foo, [:bar], "value"], [:baz, [:bar], "value"]],
24
27
  [[:foo, [:baz], "value"], [:foo, [:bar], "value"]],
25
28
  [[:foo, [Bogus::DefaultValue, :baz], "value"], [:foo, [:bar, :bar], "value"]],
29
+ [[:foo, [:bar, {foo: Bogus::DefaultValue, bar: 1}], "value"], [:foo, [:bar, {bar: 2}], "value"]],
26
30
  [[:foo, [Bogus::AnyArgs]], [:bar, [:bar]]],
27
31
  [[:foo, [:bar]], [:bar, [Bogus::AnyArgs]]],
28
32
  [[:foo, [Bogus::AnyArgs], "some value"], [:foo, [:bar], "other value"]],
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Method Copiers" do
4
+ shared_examples_for "method copier" do
5
+ let(:klass) { Class.new }
6
+ subject { isolate(described_class) }
7
+
8
+ it { should respond_to(:all) }
9
+ it { should respond_to(:get) }
10
+ it { should respond_to(:remove) }
11
+ it { should respond_to(:define) }
12
+ end
13
+
14
+ describe Bogus::InstanceMethods do
15
+ it_behaves_like "method copier"
16
+ end
17
+
18
+ describe Bogus::ClassMethods do
19
+ it_behaves_like "method copier"
20
+ end
21
+
22
+ describe Bogus::ActiveRecordAccessors do
23
+ let(:instance_methods) { nil }
24
+ it_behaves_like "method copier"
25
+ end
26
+ end
@@ -269,12 +269,16 @@ describe Bogus::MockingDSL do
269
269
  greeter.greet("Jake")
270
270
 
271
271
  greeter.should have_received.greet("Jake")
272
+ greeter.should_not have_received.greet("Bob")
272
273
  end
273
274
 
274
- it "allows chaining interactions" do
275
- greeter = fake(foo: "bar")
275
+ it "verifies mock expectations set on anonymous fakes" do
276
+ greeter = fake
277
+ mock(greeter).greet("Jake") { "Hello Jake" }
276
278
 
277
- greeter.baz.foo.should == "bar"
279
+ expect {
280
+ Bogus.after_each_test
281
+ }.to raise_error(Bogus::NotAllExpectationsSatisfied)
278
282
  end
279
283
  end
280
284
 
@@ -24,7 +24,7 @@ module Bogus
24
24
  end
25
25
 
26
26
  it "does not change the method signature" do
27
- object.greet("John").should == object
27
+ object.method(:greet).arity.should == 1
28
28
  end
29
29
 
30
30
  it "does not change the method signature" do
@@ -75,7 +75,7 @@ module Bogus
75
75
  end
76
76
 
77
77
  it "can overwrite the non-existent methods" do
78
- object.greet.should equal(object)
78
+ object.methods.should include(:greet)
79
79
  end
80
80
 
81
81
  it "can be reset back to the original state" do
@@ -21,6 +21,6 @@ describe Bogus::RecordInteractions do
21
21
  end
22
22
 
23
23
  it "returns self from record by default" do
24
- sample.__record__(:foo).should == sample
24
+ sample.__record__(:foo).should be_a_default_return_value
25
25
  end
26
26
  end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ if RUBY_VERSION >= '2.0'
4
+ describe "Ruby 2.0 keyword arguments" do
5
+ class ExampleForKeywordArgs
6
+ eval "def foo(x: raise, y: 1); end"
7
+ eval "def bar(x: 1, **rest); end"
8
+ end
9
+
10
+ include Bogus::MockingDSL
11
+
12
+ shared_examples_for "stubbing methods with keyword arguments" do
13
+ it "can spy on stubbed methods" do
14
+ stub(subject).foo(any_args)
15
+
16
+ subject.foo(x: "test")
17
+
18
+ subject.should have_received.foo(x: "test")
19
+ subject.should_not have_received.foo(x: "baz")
20
+ end
21
+
22
+ it "can mock methods with keyword arguments" do
23
+ mock(subject).foo(x: 1) { :return }
24
+
25
+ subject.foo(x: 1).should == :return
26
+
27
+ expect { Bogus.after_each_test }.not_to raise_error
28
+ end
29
+
30
+ it "can stub methods with keyword arguments" do
31
+ stub(subject).foo(x: "bar") { :return_value }
32
+
33
+ subject.foo(x: "bar").should == :return_value
34
+ end
35
+
36
+ it "raises on error on unknown keyword" do
37
+ expect {
38
+ stub(subject).foo(x: "bar", baz: "baz")
39
+ }.to raise_error(ArgumentError)
40
+ end
41
+
42
+ it "does not overwrite the method signature" do
43
+ stub(subject).foo(x: 1)
44
+
45
+ expect {
46
+ subject.foo(bar: 1)
47
+ }.to raise_error(ArgumentError)
48
+ end
49
+ end
50
+
51
+ shared_examples_for "stubbing methods with double splat" do
52
+ it "can spy on stubbed methods" do
53
+ stub(subject).bar(any_args)
54
+
55
+ subject.bar(x: "test", z: "spec")
56
+
57
+ subject.should have_received.bar(x: "test", z: "spec")
58
+ subject.should_not have_received.bar(y: "baz")
59
+ end
60
+
61
+ it "can mock methods with keyword arguments" do
62
+ mock(subject).bar(x: 1, z: 2) { :return }
63
+
64
+ subject.bar(x: 1, z: 2).should == :return
65
+
66
+ expect { Bogus.after_each_test }.not_to raise_error
67
+ end
68
+
69
+ it "can stub methods with keyword arguments" do
70
+ stub(subject).bar(x: "bar", z: "bar") { :return_value }
71
+
72
+ subject.bar(x: "bar", z: "bar").should == :return_value
73
+ end
74
+ end
75
+
76
+ context "with regular objects" do
77
+ subject { ExampleForKeywordArgs.new }
78
+
79
+ include_examples "stubbing methods with keyword arguments"
80
+ include_examples "stubbing methods with double splat"
81
+ end
82
+
83
+ context "with fakes" do
84
+ subject { fake(:example_for_keyword_args) }
85
+
86
+ it "allows spying without stubbing" do
87
+ subject.foo(x: "test")
88
+
89
+ subject.should have_received.foo(x: "test")
90
+ end
91
+
92
+ include_examples "stubbing methods with keyword arguments"
93
+ include_examples "stubbing methods with double splat"
94
+ end
95
+ end
96
+ end