[rspec-users] lots of nil problems!

Phillip Koebbe phillipkoebbe at gmail.com
Sat Mar 20 07:10:20 EDT 2010

Welcome to RSpec, Patrick. For some of us, it's pretty rocky at first. I 
started using it a couple of years ago with models, and understood that 
well enough (I think). Then I came to controllers and I just couldn't 
wrap my mind around it. I gave up for quite some time. When I came back 
to testing, it was on a project that was using test::unit, but at least 
I was working with someone who had more experience than I did, and I was 
able to gain some understanding that I lacked earlier. But during the 
use of test::unit, I realized I missed RSpec, so when I moved on, I put 
RSpec back into my workflow. I've been trudging along for a few months 
now, and while I still have lots and lots to learn, I think I am 
actually using it somewhat correctly and productively. So while I 
definitely don't want to try to supersede Nick's or anyone else's 
contributions to your questions, I thought I would chime with what I've 

On 2010-03-20 2:28 AM, Patrick J. Collins wrote:
> Hi Nick,
> Thank you very much for your reply.  One thing I am finding incredibly
> frustrating with Rspec, is that I don't even know what questions to ask--

Ask everything. In my life, I've learned that the only stupid question 
is the one you didn't ask. Most of the people in the RSpec community are 
*very* understanding, patient, and incredibly helpful. No one is going 
to bite your head off!

> because I find the whole thing so confusing.  So forgive me, but I am going to
> break down your code and ask specific questions to hopefully gain
> understanding.
> 1.  Ok-- so in your example (which I greatly appreciate), you have this do_action
> method..  Is that where I would put something like
> get :create, :format =>  :pdf
> ?
> ...
> 2. Next in the before each block, you set @address..
> Now, I have factory girl installed and have used it in cucumber, is that
> something that could be used instead of setting @address to "123 some st" ?  Is
> that common practice and acceptable to do?
> 3.  You set shipping_setting to mock the model Setting with
> :address set to @address....
> > From my understanding of what I've read--  Mocking a model,
> simply means that it's a fake object, that acts like the real
> thing------  So, when you do that mock_model, is it virtually
> the same to have just done:
> @shipping_setting = Setting.create(:address =>  @address)
> ?  That would be utilizing the test database, correct?  By
> using mock_model, nothing is being stored, right?  It's more
> just temporary data in memory... ?

No, you're not using the test database. That's the point of mocking: you 
want to break the dependency on another layer. When you test, you want 
to try to isolate what you are testing so you can specify how it behaves 
given certain criteria. For example, when you test a model, you don't 
want a controller involved. When you test a controller, you don't really 
want a model involved. Mocking and stubbing allow you to completely 
control all (or most) of the extenuating circumstances that your 
controller will find itself in. Then you can properly test something 
like "When the controller receives these params, it should do blah blah 

> 4.  You do .stub! ...........  This is where I get really
> confused.  From the peepcode screencast that I have watched
> several times, he explained that stubbing is the same as
> mocking-- except there is no expectation of what it returns.

Stubbing is creating the "plumbing" that your application expects to 
exist to function properly. If you have a person object and you want to 
do something with the name attribute, you code will be expecting 
"person.name" to work. If you have a fake object @person and call 
@person.name, you will get an error unless you stub it like

@person.stub!(:name).and_return('John Doe')

> That made sense when he said it, but in all the examples I've
> seen with code (including yours), there is this .and_return at
> the end..  Which as far as I can tell, is an expectation..  I
> mean, you are asking it to return a specific thing-- that is
> an expectation is it not?  Or does expectation really mean
> something else in this context?

The .and_return() bit just says "for this stubbed method, return this 
value when it's called." Keep in mind that these objects you are 
creating are going to be interacting with your application code. So if 
your application code calls Person.new, it expects to receive back a 
person object. So you can do something like this in your specs:

@person = stub_model(Person)

Then you will be bypassing your Person model completely but still 
sending something back for your code to play with. Now, I've introduced 
another method in this mess, stub_model. This is very similar to stub, 
except that it goes ahead and and stubs out the attribute methods that 
are on your model. So if you have Person with name, age, and gender, the 
single call to stub_model also does this for you:


By default, the stubs created with stub_model will return nil. If you 
need to specify return values, do something like this:

@person = stub_model(Person, :name => 'John Doe', :age => 99, :gender => 

> That aside, if I try to guess what this Setting.stub! this is
> doing-- it is pretending that you are actually looking for a
> record, and getting it.....  but in this case, is that even
> worth doing?  I mean, the shipping_setting record is really
> only important in the sense that the record is needed to
> provide a valid "from" address for a label..  But, if we're
> dealing with a test database where a from address doesn't
> exist-- then it seems kind of pointless..  To clarify, the
> importance for me would be to have a test that actually looks
> in my real database and makes sure there is a shipping from
> address in there...  I have no idea if this paragraph will
> make sense to you, but hopefully it will.
Here is where testing in isolation comes back into play. If you are 
testing a controller, you want to try to avoid the dependence on the 
database. Ideally, you want to use mocking and stubbing to create an 
artificial environment, that you completely control, to specify the 
behavior of your controller. Think about each situation you expect your 
controller to encounter. For each one of those situations, create the 
imaginary world that needs to exist, and then test that your controller 
behaves correctly.

For example, if your controller needs to do one thing if a particular 
record is found and something else if it is not found, you should have 
two sets of specifications. I usually do something like this:

context 'when records is found' do
   before :each do
     @record = stub_model(SomeClass)

   it 'should test something' do
     blah blah blah

context 'when record is not found' do

   it 'should test something else' do


I've thrown in another method, .should_receive. This establishes an 
expectation that this method should be called during the execution of 
your code. If it does not get called, you will get a failure. Stub!, on 
the other hand, just creates the method *in case* it gets called. No 
error will be raised if it doesn't. So in the bogus code above, I am 
saying that I expect my controller to call SomeClass.find, and I want to 
test what it does when the find is successful and when it isn't. When it 
is successful, it will be returning something that the application will 
think is an instance of the class, and when it is not successful, it 
will be returning nil, which is what normally happens in AR. However, 
because I'm "mocking and stubbing", I'm bypassing AR completely.

That's all I have time for right now. I hope this has helped a little 
bit. I encourage you to take deep breaths often and just hang in there. 
Keep asking questions. Soon or later, the light will click and you'll 
have an "Aha!" moment.


More information about the rspec-users mailing list