[rspec-users] nested blocks

Chris Hoffman chris.c.hoffman at gmail.com
Tue May 15 15:16:48 EDT 2007


Sorry about being incomplete; here is the whole error message:

NoMethodError in 'PagesController#new should populate any necessary
collections '
undefined method `get' for #<Spec::DSL::EvalModule:0xb6f2397c>
./spec/controllers/../controllers/crud_spec_helper.rb:88:
./spec/controllers/../controllers/crud_spec_helper.rb:17:in
`it_should_populate_collections'
script/spec:4:

On 5/15/07, David Chelimsky <dchelimsky at gmail.com> wrote:
> On 5/15/07, Chris Hoffman <chris.c.hoffman at gmail.com> wrote:
> > Hello,
> >
> > Does anyone have an explanation for why the following code results in
> > the error that follows?  I also would value any criticisms of my
> > approach (i.e., defining it_should_populate_collections).  Thanks
> >
> > -Chris
> >
> > #Code
> >
> > def it_should_populate_collections(condition=nil)
> >   it "should populate any necessary collections #{condition}" do
> >     [*@collections_to_populate].each do |collection|
> >       collection_model = collection.to_s.classify.constantize
> >       collection_model.should_receive(:find).with(:all).and_return("the
> > #{collection}")
> >     end
> >     yield
> >     [*@collections_to_populate].each do |collection|
> >       assigns[collection].should == "the #{collection}"
> >     end
> >   end
> > end
> >
> > describe "Foo" do
> >   before(:all) do
> >     @collections_to_populate = :bars
> >   end
> >
> >   before(:each) do
> >     @obj = Foo.new
> >   end
> >
> >   it_should_populate_collections "on a save failure" do
> >     @obj.should_receive(:save)
> >     post @action
> >   end
> > end
> >
> > #Error
> >
> > undefined method `post' for #<Spec::DSL::EvalModule:0xb6e7b2e0>
>
> post is only available in controller specs, identified by living in
> spec/controllers or by saying:
>
>   describe "Foo", :behaviour_type => :controller do
>
> My guess is that you're doing this in spec/models, but that's just a
> guess (please include complete error messages instead of just one line
> when you post questions like this).
>
> As for the approach:
>
> 1. I'd recommend only using before(:all) for expensive operations like
> initializing databases. In this example, there is no benefit to using
> before(:all). Not even a runtime benefit, because any instance vars
> that you set up get copied around which is no less expensive than
> simply re-creating them before(:each) example. Using before(:all) and
> before(:each) together just makes things confusing.
>
> 2. "it_should_populate_collections" speaks very nicely from a
> documentation standpoint, but from a failure isolation standpoint
> (i.e. understanding quickly why something fails when it does) I think
> it's a bit problematic. There's just no way to understand what's going
> on in the example without looking at the definition of
> it_should_populate_collections. It's very clever, but takes attention
> away from where it should be. The fact that it yields back to the
> current block makes it even more confusing. I'd stay away from that in
> specs.
>
> In general, I'd encourage you to use custom matchers rather than
> adding "it_blah" methods (i.e. @model.should populate_collections(:a,
> :b) ). I think that will make it much easier for other people to look
> at your specs and understand them from a documentation perspective,
> and a failure isolation perspective.
>
> 2 cents
>
> Cheers,
> David
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list