[rspec-users] collection-based finder methods

David Chelimsky dchelimsky at gmail.com
Wed Jul 22 11:39:08 EDT 2009


On Wed, Jul 22, 2009 at 10:31 AM, amkirwan<amkirwan at gmail.com> wrote:
> Thanks for the help but I guess I am not getting something. How is
> @user= = mock_model(Person) and different then the following code:

This is assigning the mock_model(Person) to a @user instance variable
in the spec. This is not the same user that is in the controller.

> message = mock_model(Message)
> Message.stub!(:new).and_return message
> message.should_receive(:save)
> post :create

This creates a mock_model(Message) and then tells Message to return it
when it receives :new, therefore message in the spec is the same
object as Message.new in the controller.

> def create
> message = Message.new params[:new]
> message.save
> end
> I guess I don't understand why assigns[:letter] is expecting a Person
> instance instead of a Letter instance

I'm not clear on what you mean by this. Would you please post the full
error message (either here or in a pastie or gist)?

>
> On Jul 22, 10:42 am, David Chelimsky <dchelim... at gmail.com> wrote:
>> On Wed, Jul 22, 2009 at 9:12 AM, amkirwan<amkir... at gmail.com> wrote:
>> > My spec is a messed up because I have tried everything I can think of
>> > to mock but this is what I have for the show method. The @user
>> > instance is setup in the login_and_before_filter_pass macros with the
>> > following: @user = mock_model(Person, :null_object => true)
>>
>> > The error I keep receiving is that assigns[:letter].should equal
>> > @letter keeps return that it is expecting a Person object instead of a
>> > Letter object. The only way I can get it to pass is by putting
>> > @user.letters.should_receive(:find).with("1").and_return(@letter)
>> > directly in the "should assign the found letter for the view"
>>
>> > I feel like I must be missing something about how stubbing and mocking
>> > work
>>
>> >  # Get /admin/letters/1
>> >  def show
>> >    id = params[:id]
>> >    @letter =  @user.letters.find(id)
>> >  end
>>
>> > describe Admin::LettersController, "SHOW GET /admin/letters/1" do
>>
>> >  before(:each) do
>> >    @user.letters.should_receive(:find).with("1").and_return(@letter)
>>
>> This @user is an instance variable in the spec, and is not the same
>> @user that is in the controller.
>>
>> HTH,
>> David
>>
>>
>>
>>
>>
>> >  end
>>
>> >  def do_get
>> >    put :show, {:id => "1"}, @session
>> >  end
>>
>> >  login_and_before_filter_pass(:filter => :admin_only,
>> >                             :request_method => :get,
>> >                             :action => :show,
>> >                             :parameters => {:cas_user => 'ak730'})
>>
>> >  it "should be successful" do
>> >    do_get
>> >    response.should be_success
>> >  end
>>
>> >  it "should find the letter requested" do
>> >    @user.letters.should_receive(:find).with("1").and_return(@letter)
>> >    puts(@letter)
>> >    do_get
>> >  end
>>
>> >  it "should assign the found letter for the view" do
>> >    # uncommenting will allow to pass
>> >    # @user.letters.should_receive(:find).with("1").and_return
>> > (@letter)
>> >    do_get
>> >    assigns[:letter].should equal(@letter)
>> >  end
>>
>> >  it "should render show template" do
>> >    do_get
>> >    response.should render_template("show")
>> >  end
>>
>> > end
>>
>> > On Jul 22, 9:13 am, David Chelimsky <dchelim... at gmail.com> wrote:
>> >> On Tue, Jul 21, 2009 at 11:21 PM, amkirwan<amkir... at gmail.com> wrote:
>> >> > How do I spec this following example from the Agile Rails Book listed
>> >> > below. I am doing a similar thing in my controller and when I
>> >> > attempted to change it to the collection way of doing the find I am
>> >> > unable to get my spec to pass though I know it is working fine as my
>> >> > cucumber features are passing
>>
>> >> > old rails way:
>>
>> >> > def show
>> >> > @order = Order.find(params[:id])
>> >> > end
>>
>> >> > new rails way collection-based:
>>
>> >> > def show
>> >> > id = params[:id]
>> >> > @order = @user.orders.find(id)
>>
>> >> This code is inherently untestable in an isolated/granular way. Your
>> >> options are:
>>
>> >> * write higher level specs that use real data
>> >>   * pros: simplicity and clarity in both code and specs
>> >>   * cons: brittle due to runtime dependency on correct models, runs slow
>>
>> >> * write a very invasive spec with complex setup and instance_eval to
>> >> set up the @user
>> >>   * pros: runs fast, no runtime dependency on correct models
>> >>   * cons: brittle due to dependency on internals, complex
>>
>> >> * refactor the code to make it easier to spec
>> >>   * pros: more highly decoupled code, simpler specs, fast
>> >>   * cons: more work up front, may disregard some of what Rails has to offer
>>
>> >> Note that the first two options are both brittle, but for different
>> >> reasons. The first is brittle due to a runtime dependency. That means
>> >> that when you run the spec the model has to be working correctly for
>> >> the spec to pass, and a failure could be due to a problem in the model
>> >> or in the controller.
>>
>> >> The second is due to a code dependency. That means that when you want
>> >> to change this code, the spec will have to change as well. This is
>> >> true of any case in which you use mocks or stubs to varying degrees,
>> >> and that comes with its own tradeoffs. In this case, the necessary
>> >> stubbing would be complex and invasive enough that it would be a
>> >> concern to me.
>>
>> >> Getting to your original question - what does your spec look like now,
>> >> and what failure message are you getting?
>>
>> >> Cheers,
>> >> David
>>
>> >> > rescue
>> >> > redirect_to :action => "index"
>> >> > end
>> >> > _______________________________________________
>> >> > rspec-users mailing list
>> >> > rspec-us... at rubyforge.org
>> >> >http://rubyforge.org/mailman/listinfo/rspec-users
>>
>> >> _______________________________________________
>> >> rspec-users mailing list
>> >> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users
>> > _______________________________________________
>> > rspec-users mailing list
>> > rspec-us... at rubyforge.org
>> >http://rubyforge.org/mailman/listinfo/rspec-users
>>
>> _______________________________________________
>> rspec-users mailing list
>> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list