spec/bogus/mocking_dsl_spec.rb in bogus-0.0.2 vs spec/bogus/mocking_dsl_spec.rb in bogus-0.0.3.rc.1
- old
+ new
@@ -2,31 +2,68 @@
describe Bogus::MockingDSL do
class ExampleFoo
def foo(bar)
end
+
+ def hello(greeting, name)
+ end
+
+ def self.bar(baz)
+ "Hello #{baz}"
+ end
end
class Stubber
extend Bogus::MockingDSL
end
+ before do
+ Bogus.send(:clear_expectations)
+ end
+
describe "#stub" do
- it "allows stubbing the existing methods" do
- baz = ExampleFoo.new
+ let(:baz) { ExampleFoo.new }
+ it "allows stubbing the existing methods" do
Stubber.stub(baz).foo("bar") { :return_value }
baz.foo("bar").should == :return_value
end
+ it "can stub method with any parameters" do
+ Stubber.stub(baz).foo(Stubber.any_args) { :default_value }
+ Stubber.stub(baz).foo("bar") { :foo_value }
+
+ baz.foo("a").should == :default_value
+ baz.foo("b").should == :default_value
+ baz.foo("bar").should == :foo_value
+ end
+
+ it "can stub method with some wildcard parameters" do
+ Stubber.stub(baz).hello(Stubber.any_args) { :default_value }
+ Stubber.stub(baz).hello("welcome", Stubber.anything) { :greeting_value }
+
+ baz.hello("hello", "adam").should == :default_value
+ baz.hello("welcome", "adam").should == :greeting_value
+ baz.hello("welcome", "rudy").should == :greeting_value
+ end
+
it "does not allow stubbing non-existent methods" do
baz = ExampleFoo.new
expect do
Stubber.stub(baz).does_not_exist("bar") { :return_value }
end.to raise_error(NameError)
end
+
+ it "unstubs methods after each test" do
+ Stubber.stub(ExampleFoo).bar("John") { "something else" }
+
+ Bogus.after_each_test
+
+ ExampleFoo.bar("John").should == "Hello John"
+ end
end
describe "#have_received" do
context "with a fake object" do
let(:the_fake) { Bogus.fake_for(:example_foo) }
@@ -50,30 +87,97 @@
end
end
it "can be used with plain old Ruby objects" do
object = ExampleFoo.new
- stub(object).foo
+ Stubber.stub(object).foo(Stubber.any_args)
object.foo('test')
object.should Stubber.have_received.foo("test")
end
+
+ class ClassWithMatches
+ def matches?(something)
+ end
+ end
+
+ it "can be used with objects that have same methods as an RSpec expectation" do
+ fake = Bogus.fake_for(:class_with_matches)
+
+ fake.matches?("foo")
+
+ fake.should Bogus.have_received.matches?("foo")
+ end
+
+ class PassesSelfToCollaborator
+ def hello(example)
+ example.foo(self)
+ end
+ end
+
+ it "can be used with self references" do
+ Bogus.record_calls_for(:passes_self_to_collaborator)
+
+ fake = Bogus.fake_for(:example_foo)
+ object = PassesSelfToCollaborator.new
+
+ object.hello(fake)
+
+ fake.should Bogus.have_received.foo(object)
+ end
end
class Mocker
extend Bogus::MockingDSL
end
describe "#mock" do
- it "allows mocking the existing methods" do
- baz = ExampleFoo.new
+ let(:object) { ExampleFoo.new }
+ let(:fake) { Bogus.fake_for(:example_foo) { ExampleFoo } }
- Mocker.mock(baz).foo("bar") { :return_value }
+ shared_examples_for "mocking dsl" do
+ before do
+ Mocker.mock(baz).foo("bar") { :return_value }
+ end
- baz.foo("bar").should == :return_value
+ it "allows mocking the existing methods" do
+ baz.foo("bar").should == :return_value
+ end
+
+ it "verifies that the methods mocked exist" do
+ expect {
+ Mocker.mock(baz).does_not_exist { "whatever" }
+ }.to raise_error(NameError)
+ end
+
+ it "raises errors when mocks were not called" do
+ expect {
+ Bogus.after_each_test
+ }.to raise_error(Bogus::NotAllExpectationsSatisfied)
+ end
+
+ it "clears the data between tests" do
+ Bogus.send(:clear_expectations)
+
+ expect {
+ Bogus.after_each_test
+ }.not_to raise_error(Bogus::NotAllExpectationsSatisfied)
+ end
end
+
+ context "with fakes" do
+ it_behaves_like "mocking dsl" do
+ let(:baz) { fake }
+ end
+ end
+
+ context "with regular objects" do
+ it_behaves_like "mocking dsl" do
+ let(:baz) { object }
+ end
+ end
end
describe "#fake" do
include Bogus::MockingDSL
@@ -109,8 +213,131 @@
it "allows chaining interactions" do
greeter = fake(foo: "bar")
greeter.baz.foo.should == "bar"
+ end
+ end
+
+ class SampleOfConfiguredFake
+ def self.foo(x)
+ end
+
+ def self.bar(x, y)
+ end
+
+ def self.baz
+ end
+ end
+
+ describe "globally configured fakes" do
+ before do
+ Bogus.fakes do
+ fake(:globally_configured_fake, as: :class, class: proc{SampleOfConfiguredFake}) do
+ foo "foo"
+ bar { "bar" }
+ baz { raise "oh noes!" }
+ end
+ end
+ end
+
+ it "returns configured fakes" do
+ the_fake = Stubber.fake(:globally_configured_fake)
+
+ the_fake.foo('a').should == "foo"
+ the_fake.bar('a', 'b').should == "bar"
+ end
+
+ it "allows overwriting stubbed methods" do
+ the_fake = Stubber.fake(:globally_configured_fake, bar: "baz")
+
+ the_fake.foo('a').should == "foo"
+ the_fake.bar('a', 'b').should == "baz"
+ end
+
+ it "evaluates the block passed to method in configuration when method is called" do
+ the_fake = Stubber.fake(:globally_configured_fake)
+
+ expect{ the_fake.baz }.to raise_error("oh noes!")
+ end
+ end
+
+ describe "faking classes" do
+ class ThisClassWillBeReplaced
+ def self.hello(name)
+ "Hello, #{name}"
+ end
+ end
+ TheOriginalClass = ThisClassWillBeReplaced
+
+ after do
+ Bogus.reset_overwritten_classes
+ end
+
+ it "replaces the class for the duration of the test" do
+ Stubber.fake_class(ThisClassWillBeReplaced, hello: "replaced!")
+
+ ThisClassWillBeReplaced.hello("foo").should == "replaced!"
+ ThisClassWillBeReplaced.should_not equal(TheOriginalClass)
+ end
+
+ it "makes it possible to spy on classes" do
+ Stubber.fake_class(ThisClassWillBeReplaced)
+
+ ThisClassWillBeReplaced.hello("foo")
+
+ ThisClassWillBeReplaced.should Bogus.have_received.hello("foo")
+ ThisClassWillBeReplaced.should_not Bogus.have_received.hello("bar")
+ end
+
+ it "restores the class after the test has finished" do
+ Stubber.fake_class(ThisClassWillBeReplaced)
+ Bogus.reset_overwritten_classes
+
+ ThisClassWillBeReplaced.should equal(TheOriginalClass)
+ end
+ end
+
+ class SampleForContracts
+ def initialize(name)
+ @name = name
+ end
+
+ def greet(greeting = "Hello")
+ "#{greeting}, #{@name}!"
+ end
+ end
+
+ describe "contracts" do
+ let(:sample) { SampleForContracts.new("John") }
+
+ before do
+ Bogus.reset!
+
+ Stubber.fake(:sample_for_contracts, greet: "Welcome, John!")
+
+ Bogus.after_each_test
+
+ Bogus.record_calls_for(:sample_for_contracts)
+ end
+
+ it "passes when all the mocked interactions were executed" do
+ sample.greet("Welcome").should == "Welcome, John!"
+
+ Bogus.after_each_test
+
+ expect {
+ Bogus.verify_contract!(:sample_for_contracts)
+ }.not_to raise_error
+ end
+
+ it "fails when contracts are fullfilled" do
+ sample.greet("Hello").should == "Hello, John!"
+
+ Bogus.after_each_test
+
+ expect {
+ Bogus.verify_contract!(:sample_for_contracts)
+ }.to raise_error(Bogus::ContractNotFulfilled)
end
end
end