Awesome.  I totally get it, but is that how you're always supposed to spec
out associations and all the methods that go with an association like
"create" and such?  I'm interested in that because I'm specing a lot of code
that deals heavily with code that has associations going on, yet none of the
examples of RSpec use I come across have anything about associations and
RSpec.  I don't imagine they'd be handled too differently, but it's just
something wondered about.

Right now, I'm testing and building up a controller and so far my tests have
been passing as long as I don't run into any examples that involve
associations.  This code, for example, has been giving me a few issues:

# my users_controller_spec.rb (or at least, the relevant part)

describe UsersController do
  fixtures :users

  before(:each) do
    @tiffani = users(:tiffani)
    @users = [EMAIL PROTECTED]
    @users.stub!(:build).and_return(@tiffani)
    @mock_account = mock_model(Account, :users => @users, :save => true)
  end

  describe "when creating a User" do
    it "should return the registration form for adding a User on GET new" do
      User.should_receive(:new).once
      get :new
    end

    it "should render the new User registration form on GET new" do
      get :new
      response.should render_template("users/new")
    end

    it "should create a new User and then redirect to that User's profile on
POST create" do
      @mock_account.should_receive(:new)
      post :create, :new_user => { :first_name => @tiffani.first_name,
:last_name => @tiffani.last_name,
                                   :email_address =>
@tiffani.email_address  }
    end

    it "should redirect to users/new when User is setup with invalid data"
  end

  # ...
end

And in users_controller.rb:

def create
    @new_account = Account.new(params[:account])
    @new_user = @new_account.users.build(params[:new_user])

    respond_to do |wants|
      if @new_account.save
        flash[:notice] = "Welcome, #{ @new_user.first_name }!"
        wants.html { redirect_to(user_url(@new_user)) }
      else
        wants.html { render :action => "new" }
      end
    end
  end


When I run the tests the third test fails and RSpec complains that "Mock
'Account_1003' expected :new with (any args) once, but received it 0 times"

I'm confused about that since I am calling Account.new in the create method
on the controller.  What's really wrong here?

Thanks in advance for answering my RSpec questions! :D

--Tiffani AB


On Thu, Jul 3, 2008 at 9:09 PM, Mikel Lindsaar <[EMAIL PROTECTED]> wrote:

> On Fri, Jul 4, 2008 at 8:32 AM, Tiffani Ashley Bell
> <[EMAIL PROTECTED]> wrote:
> > Hi everybody,
>
> Hi Tiffany, welcome to Rspec
>
> > I was reading the Typo source code, however, and came across some code
> that
> > I didn't know exactly how it worked.  I've noticed that in testing one of
> > their controllers, they use a variable (@comments) that they don't
> declare
> > anywhere else, yet they use it as a stand in for collections on some of
> the
> > mocks.  How is that possible?  I know in the mocking documentation it
> says
> > that you can define collaborations with other objects before those
> objects
> > exist, but how is that working in this code?  I only ask that because
> later,
> > you see code like this:  @comments.stub!(:build).and_return(@comment).
>
> If you have a look at the descriptions, they use :shared => true.
> This is a way of being DRY in RSpec (which I personally don't think is
> such a good idea).
>
> What the shared => true declaration allows you to do is to include
> that block of code elsewhere with 'it should behave like my shared
> code'
>
> So we have (describe "All Requests", :shared => true do)
>
> and then the next description block is:
>
> describe "General Comment Creation", :shared => true do
>  it_should_behave_like "All Requests"
>
> Which then includes the All Requests block (which is just a before method).
>
> The @comments variable gets declared in:
>
> @comments.stub!(:build).and_return(@comment)
>
> and then this is tied in to the Article model in the _previous_ code
> block like so:
>
>    @article  = mock_model(Article,
>                  :comments                   => @comments,
>                  :published_comments         => @comments,
>                  :add_comment                => @comment)
>
>
> So when you call @article.comments you get @comments as a stub back
> which stubs :build and returns a @comment.
>
> Ugh.
>
> This is where, in RSpec, you can dig a very fast grave.  Because
> you'll come back to this code in 6-12 months and be totally stuck
> trying to figure out what is where.
>
> I recently wrote a viewpoint on this that might help you:
>
> http://www.lindsaar.net/2008/6/24/tip-24-being-clever-in-specs-is-for-dummies
>
> Hope you do well with Rspec, feel free to ask more questions!
>
> --
> http://lindsaar.net/
> Rails, RSpec, Puppet and Life blog....
> _______________________________________________
> rspec-users mailing list
> rspec-users@rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to