Skip to content

Commit

Permalink
Merge pull request #3 from ivanacostarubio/master
Browse files Browse the repository at this point in the history
Add at_least and at_most expectations.
  • Loading branch information
chuyeow committed Apr 15, 2013
2 parents 5bc73bd + 89cc1f0 commit 215d8ac
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 5 deletions.
15 changes: 14 additions & 1 deletion README.md
Expand Up @@ -33,6 +33,18 @@ You can now write [Bacon](https://github.com/chneukirchen/bacon) specs like this

get('/people/show/1')
end

it "knows how many times we call a method" do
Person.should.receive(:find).at_least(3)

Person.list
end

it "can use at_most" do
Person.should.receive(:find).at_most(3)

Person.list
end
end
```

Expand Down Expand Up @@ -78,14 +90,15 @@ Todos
* test/unit and RSpec integration.
* Remove the `$facon_mocks` global.
* Throw away unnecessary code.
* Implement `exactly`, `at_least`, `at_most` expectations.
* Implement `exactly` expectation.

Contributors
------------

* [James Tucker](https://github.com/raggi) for #times, #once, #never expectation matchers.
* [Peter Kim](https://github.com/petejkim) for [MacBacon](https://github.com/alloy/MacBacon) support.
* [Yossef Mendelssohn](https://github.com/ymendel) for Ruby 1.9.2 compatibility fixes.
* [Ivan Acosta-Rubio](https://github.com/ivanacostarubio) for at_most and at_least expectations.

Thanks to
---------
Expand Down
27 changes: 24 additions & 3 deletions lib/facon/expectation.rb
Expand Up @@ -79,14 +79,27 @@ def invoke(args, block)
end

# Returns true if this expectation has been met.
# TODO at_least and at_most conditions
def met?
return true if @expected_received_count == :any ||
@expected_received_count == @actual_received_count
return true if meets_at_most_requirements? ||
meets_at_least_requirements? ||
(@expected_received_count == :any) ||
(@expected_received_count == @actual_received_count)

raise_expectation_error(self)
end

def at_least(val)
@at_least = true
@expected_received_count = val
self
end

def at_most(val)
@at_most = true
@expected_received_count = val
self
end

# Returns true if the given <code>method</code> and arguments match this
# Expectation.
def matches(method, args)
Expand All @@ -113,6 +126,14 @@ def once; times(1); end
def never; times(0); end

private
def meets_at_most_requirements?
@at_most and ((@expected_received_count >= @actual_received_count) && (@actual_received_count != 0))
end

def meets_at_least_requirements?
@at_least and @actual_received_count >= @expected_received_count
end

def check_arguments(args)
case @argument_expectation
when :any then true
Expand Down
66 changes: 65 additions & 1 deletion spec/stub_spec.rb
Expand Up @@ -93,6 +93,7 @@ def existing_instance_method
end

it "should ignore when the stubbed method is never called" do
true.should == true
end
end

Expand All @@ -104,10 +105,11 @@ def existing_instance_method
end

it "should ignore when never called" do
true.should == true
end

it "should ignore when called with expected argument" do
@object.stubbed_method(:expected_arg)
@object.stubbed_method(:expected_arg).should == :stubbed_value
end

it "should raise a NoMethodError when called with no arguments" do
Expand All @@ -125,3 +127,65 @@ def existing_instance_method
@object.stubbed_method(:something_else).should == :bar
end
end


describe "A Method stub" do

before do
@mock= Object.new
@mock.stub!(:stubbed_method).with(:expected_arg).and_return(:stubbed_value)
end


describe "can use at_least" do
it "fails if method is never called" do
@mock.should.receive(:message).at_least(4)
lambda{
@mock.spec_verify
}.should.raise(Facon::MockExpectationError).message.should == "Mock 'Object' expected :message with (any args) 4 times, but received it 0 times"
end

it "fails if the method gets call less times that expected" do
@mock.should.receive(:message).at_least(4)
3.times { @mock.message }
lambda{ @mock.spec_verify }.should.raise(Facon::MockExpectationError)
end

it "passed when the method is call" do
@mock.should.receive(:message).at_least(4)
4.times { @mock.message }
lambda{ @mock.spec_verify}.should.not.raise
end

it "is ok if we call the method more times that required" do
@mock.should_receive(:message).at_least(4)
5.times{ @mock.message}
lambda{ @mock.spec_verify }.should.not.raise
end
end

describe "can use at most" do
it "fails if never called" do
@mock.should.receive(:message).at_most(3)
lambda{ @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'Object' expected :message with (any args) 3 times, but received it 0 times"
end

it "fails when call more expected" do
@mock.should.receive(:message).at_most(3)
4.times { @mock.message }
lambda{ @mock.spec_verify }.should.raise(Facon::MockExpectationError).message.should == "Mock 'Object' expected :message with (any args) 3 times, but received it 4 times"
end

it "passes when the method is call less times that expected" do
@mock.should.receive(:message).at_most(3)
2.times { @mock.message }
lambda{ @mock.spec_verify}.should.not.raise(Facon::MockExpectationError)
end

it "passes when we call the method axactly the same number of times" do
@mock.should.receive(:message).at_most(3)
3.times { @mock.message }
lambda{ @mock.spec_verify}.should.not.raise(Facon::MockExpectationError)
end
end
end

0 comments on commit 215d8ac

Please sign in to comment.