Skip to content

Commit

Permalink
Capture all information about the mock
Browse files Browse the repository at this point in the history
Before we were only capturing the object the mock was on, but not the
method being mocked, block or options.
  • Loading branch information
se3000 committed Aug 1, 2013
1 parent a3cdda9 commit 4819967
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 93 deletions.
12 changes: 6 additions & 6 deletions lib/better_receive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
require "better_receive/stub"

module BetterReceive
def better_receive(*args, &block)
Mock.new(self).assert_with(*args, &block)
def better_receive(selector, options={}, &block)
Mock.new(self, selector, options, &block).assert
end

def better_not_receive(*args, &block)
Mock.new(self).assert_negative_with(*args, &block)
def better_not_receive(selector, options={}, &block)
Mock.new(self, selector, options, &block).assert_negative
end

def better_stub(*args, &block)
Stub.new(self).assert_with(*args, &block)
def better_stub(selector, options={}, &block)
Stub.new(self, selector, options, &block).assert
end
end

Expand Down
7 changes: 5 additions & 2 deletions lib/better_receive/base.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
module BetterReceive
class Base

def initialize(subject)
def initialize(subject, message, options={}, &block)
@subject = subject
@selector = message.is_a?(Hash) ? message : message.to_sym
@options = options
@block = block
end


private

attr_reader :subject
attr_reader :subject, :selector, :options, :block

def subject_is_any_instance?
defined?(RSpec::Mocks::AnyInstance) && subject.is_a?(RSpec::Mocks::AnyInstance::Recorder)
Expand Down
6 changes: 2 additions & 4 deletions lib/better_receive/mock.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
module BetterReceive
class Mock < Base

def assert_with(selector, options={}, &block)
selector = selector.to_sym
def assert
if subject_is_any_instance?
subject.instance_variable_set(:@expectation_set, true)
any_instance_better_expect(selector, options, &block)
Expand All @@ -12,8 +11,7 @@ def assert_with(selector, options={}, &block)
end
end

def assert_negative_with(selector, options={}, &block)
selector = selector.to_sym
def assert_negative
if subject_is_any_instance?
subject.instance_variable_set(:@expectation_set, true)
any_instance_better_not_expect(selector, options, &block)
Expand Down
10 changes: 5 additions & 5 deletions lib/better_receive/stub.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
module BetterReceive
class Stub < Base

def assert_with(selector_or_hash, options={}, &block)
if selector_or_hash.is_a?(Hash)
selector_or_hash.each do |selector, value|
better_stub_method(selector, options, &block).and_return(value)
def assert
if selector.is_a?(Hash)
selector.each do |single_selector, value|
better_stub_method(single_selector.to_sym, options, &block).and_return(value)
end
else
better_stub_method(selector_or_hash, options, &block)
better_stub_method(selector, options, &block)
end
end

Expand Down
76 changes: 46 additions & 30 deletions spec/lib/better_receive/mock_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,29 @@ def bar(baz = nil)
end
end

describe "#assert_with" do
describe "#assert" do
let(:foo) { Foo.new }
let(:br_mock) { BetterReceive::Mock.new(foo) }
let(:selector) { :bar }
let(:br_mock) { BetterReceive::Mock.new(foo, selector) }

it "determines whether an object responds to a method" do
foo.should_receive(:respond_to?).with(:bar).and_return(true)

br_mock.assert_with :bar
br_mock.assert

foo.bar
end

it "raises an error if the method is not defined" do
expect {
br_mock.assert_with :bar_baz
}.to raise_error(RSpec::Expectations::ExpectationNotMetError) { |error|
error.message.should =~ /to respond to :bar_baz/
}
context "when the method is not defined" do
let(:selector) { :bar_baz }

it "raises an error if the method is not defined" do
expect {
br_mock.assert
}.to raise_error(RSpec::Expectations::ExpectationNotMetError) { |error|
error.message.should =~ /to respond to :bar_baz/
}
end
end

it "returns an rspec message expectation" do
Expand All @@ -33,7 +38,7 @@ def bar(baz = nil)
end

it "responds to additional matchers(:with, :once...)" do
br_mock.assert_with(:bar).with('wibble')
br_mock.assert.with('wibble')

foo.bar('wibble')
end
Expand All @@ -42,9 +47,10 @@ def bar(baz = nil)
let(:selector) { :bar }
let(:options) { {passed: true} }
let(:block_param) { Proc.new {} }
let(:br_mock) { BetterReceive::Mock.new(foo, selector, options, &block_param) }

before do
br_mock.assert_with(:bar, options, &block_param)
br_mock.assert

@expectation = RSpec::Mocks.proxy_for(foo).send(:method_doubles)[0][:expectations][0]
end
Expand All @@ -69,13 +75,14 @@ def bar(baz = nil)
end

context "on .any_instance" do
let(:br_mock) { BetterReceive::Mock.new(Foo.any_instance) }
let(:selector) { :bar }
let(:br_mock) { BetterReceive::Mock.new(Foo.any_instance, selector) }

context "when the method is defined" do
context "and the method is called" do
it 'does not raise an error' do
expect {
br_mock.assert_with(:bar)
br_mock.assert
foo.bar
}.to_not raise_error
end
Expand All @@ -84,7 +91,7 @@ def bar(baz = nil)
context 'and the method is not called' do
it 'does raise an error' do
expect {
br_mock.assert_with(:bar)
br_mock.assert
RSpec::Mocks::space.verify_all
}.to raise_error(RSpec::Mocks::MockExpectationError) { |error|
error.message.should == "Exactly one instance should have received the following message(s) but didn't: bar"
Expand All @@ -94,9 +101,11 @@ def bar(baz = nil)
end

context 'when the method is not defined' do
let(:selector) { :baz }

it 'raises an error' do
expect {
br_mock.assert_with(:baz)
br_mock.assert
}.to raise_error { |error|
error.message.should == "Expected instances of Foo to respond to :baz"
}
Expand All @@ -105,20 +114,24 @@ def bar(baz = nil)
end
end

describe "#assert_negative_with" do
describe "#assert_negative" do
let(:foo) { Foo.new }
let(:br_mock) { BetterReceive::Mock.new(foo) }
let(:selector) { :bar }
let(:br_mock) { BetterReceive::Mock.new(foo, selector) }

it "raises an error if the method is not defined" do
expect {
br_mock.assert_negative_with :bar_baz
}.to raise_error(RSpec::Expectations::ExpectationNotMetError) { |error|
error.message.should =~ /to respond to :bar_baz/
}
context "when the method is not defined" do
let(:selector) { :bar_baz }
it "raises an error" do
expect {
br_mock.assert_negative
}.to raise_error(RSpec::Expectations::ExpectationNotMetError) { |error|
error.message.should =~ /to respond to :bar_baz/
}
end
end

it "returns an rspec message expectation" do
br_mock.assert_negative_with(:bar).should be_a RSpec::Mocks::MessageExpectation
br_mock.assert_negative.should be_a RSpec::Mocks::MessageExpectation

expect {
foo.bar
Expand All @@ -128,7 +141,7 @@ def bar(baz = nil)
end

it "responds to additional matchers(:with, :once...)" do
br_mock.assert_negative_with(:bar).with('wibble')
br_mock.assert_negative.with('wibble')
expect {
foo.bar('wibble')
}.to raise_error(RSpec::Mocks::MockExpectationError) { |error|
Expand All @@ -140,9 +153,10 @@ def bar(baz = nil)
let(:selector) { :bar }
let(:options) { {passed: true} }
let(:block_param) { Proc.new {} }
let(:br_mock) { BetterReceive::Mock.new(foo, selector, options, &block_param) }

before do
br_mock.assert_negative_with(:bar, options, &block_param)
br_mock.assert_negative

@expectation = RSpec::Mocks.proxy_for(foo).send(:method_doubles)[0][:expectations][0]
end
Expand All @@ -163,11 +177,12 @@ def bar(baz = nil)
end

context "on .any_instance" do
let(:br_mock) { BetterReceive::Mock.new(Foo.any_instance) }
let(:selector) { :bar }
let(:br_mock) { BetterReceive::Mock.new(Foo.any_instance, selector) }

it 'raises when called' do
expect {
br_mock.assert_negative_with(:bar)
br_mock.assert_negative
foo.bar
}.to raise_error(RSpec::Mocks::MockExpectationError) { |error|
error.message.should include "received: 1 time"
Expand All @@ -176,15 +191,16 @@ def bar(baz = nil)

it 'does not raise an error if not called' do
expect {
br_mock.assert_negative_with(:bar)
br_mock.assert_negative
RSpec::Mocks::space.verify_all
}.to_not raise_error
end

context 'when the method is not defined' do
let(:selector) { :baz }
it 'raises an error' do
expect {
br_mock.assert_negative_with(:baz)
br_mock.assert_negative
}.to raise_error { |error|
error.message.should == "Expected instances of Foo to respond to :baz"
}
Expand Down
Loading

0 comments on commit 4819967

Please sign in to comment.