问题
I'm trying to use rspec's mocking to setup expectations that I can verify in the it "should" methods... but I don't know how to do this... when i call the .should_receive methods on the mock, it verifies the expected call as soon as the before :all method exits.
here's a small example:
describe Foo, "when doing something" do
before :all do
Bar.should_recieve(:baz)
foo = Foo.new
foo.create_a_Bar_and_call_baz
end
it "should call the bar method" do
# ??? what do i do here?
end
end
How can i verify the expected call in the 'it "should"' method? do i need to use mocha or another mocking framework instead of rspec's? or ???
回答1:
I'm going to take another whack at this, because it's clear from the initial set of answers and responses that there was some confusion about what you are trying to accomplish. Let me know if this is closer to what you are trying to do.
describe Foo, "when frobbed" do
before :all do
@it = Foo.new
# Making @bar a null object tells it to ignore methods we haven't
# explicitly stubbed or set expectations on
@bar = stub("A Bar").as_null_object
Bar.stub!(:new).and_return(@bar)
end
after :each do
@it.frob!
end
it "should zap a Bar" do
@bar.should_receive(:zap!)
end
it "should also frotz the Bar" do
@bar.should_receive(:frotz!)
end
end
Incidentally, although it works I'm not a big fan of the Bar.stub!(:new)
pattern; I usually prefer to pass collaborators in via optional arguments, e.g. @it.frob!(@bar)
. When not given an explicit argument (e.g. in the production code), the collaborator can be defaulted: def frob!(bar=Bar.new)
. This keeps the tests a little less bound to internal implementation.
回答2:
As a general rule you should never put an expectation in a before
block. before
blocks are for setting up state that is shared across several examples (it
blocks). Put the expectation in the example itself. E.g.:
describe Foo, "when doing something" do
before :all do
@foo = Foo.new
end
it "should call the bar method" do
Bar.should_recieve(:baz)
@foo.create_a_Bar_and_call_baz
end
end
I generally try to have my describe
block describe a particular state (e.g. describe Car, "given a full tank of gas"
), rather than describing an action.
回答3:
The should_receive method is used to setup your mock object to return something specific when the method is called. Here's an example:
Bar.should_recieve(:baz).with.({:arg1 => 'this is arg1', :arg2 => 'this is arg2'}).and_return(true)
Typically, with BDD, you want to test the behavior of your app. Testing which methods were called in order to build the proper behavior is irrelevant. If one day you decide to remove the baz method, you'll have to update your tests even though the behavior of your app won't have changed.
I think you're trying to use should_receive in a way that it wasn't meant to work like.
回答4:
I know this is an old conversation but just in case somebody still needed a right answer, here I write an example on how to validate rpec mocks spectations:
require 'spec'
require 'spec/mocks'
include Spec::Mocks::ExampleMethods
o = mock('object')
o.should_receive(:respond_to?).once
space = Spec::Mocks::Space.new
space.add o
# here we should invoke methods, o.respond_to?:foo for instance
space.verify_all
cheers
回答5:
Maybe I'm looking at it simplistically, but, do you need to verify that interaction with Bar more than once? If so, ok, but I'm not sure. In other words, are you mixing contexts?
If not, then it's not really context so much as it's part of the observation, which would make it naturally belong to the it block.
来源:https://stackoverflow.com/questions/1583760/rspec-mocks-verify-expectations-in-it-should-methods