[rspec-users] isolating controller tests from models

David Chelimsky dchelimsky at gmail.com
Sat Mar 31 11:50:27 UTC 2012

On Sat, Mar 31, 2012 at 2:49 AM, Justin Ko <jko170 at gmail.com> wrote:
> On Mar 30, 2012, at 11:11 PM, Fearless Fool wrote:
>> This is a rehash of a question I posed at:
>> http://stackoverflow.com/questions/9952317/isolating-controller-tests-from-models
>> The basic question: If I have a FoosController and a Foo model, can I
>> run FoosController rspec tests without creating the foos database table?
>> I haven't found a good way to avoid it.
>> Consider this simple controller:
>>   # file: app/controllers/foos_controller.rb
>>   class FoosController < ApplicationController
>>     respond_to :json
>>     def create
>>       @foo = Foo.create(params[:foo])
>>       respond_with @foo
>>     end
>>   end
>> In my RSpec tests, I can do
>>   @foo = mock_model("Foo")
>>   Foo.stub(:create) { @foo }
>>   post :create, :format => :json
>> ... but that fails in the call to respond_with @foo, because
>> ActionController calls @foo.has_errors? which in turn hits the database
>> to look up column names.

mock_model is not an ActiveRecord object, so if it's hitting the db
then something's not wired up correctly.

> I could stub out has_errors?, but that means
>> that I'm reaching into the internals of the system -- probably not a
>> good idea for a test suite.
> Oh, the irony!
> You're using rspec-rails, which reaches *much further* into the "system" than `has_errors?`.

There's a difference between a library doing this and end-user specs
doing this. They both bear risk, but the burden is on the library
developer (and in one place) if it's the lib, whereas its on all end
users who stray on their own.

> Mucking with a non-public API is not a "never ever" thing :)

Care to elaborate on what the risks are and when you think it's worth it?

>> If the answer to my question "can I do controller testing without
>> creating the underlying database tables?" is 'no', then I'll accept that
>> (with regret).  But I'd rather hear that it is somehow possible.

Of course its possible - just a matter of whether its worth it. This
relates to an earlier question which I believe you posted about why
the generated controller specs changed for rails 3. respond_with is
another addition to rails 3 that tightly couples controllers to
models, making it more challenging to stub models in controller specs.
If you're going to violate the "mock your code, not other people's"
guideline, you might find it safer to do it at a higher level of
abstraction: mock respond_with directly on the controller. Still a
violation of stub/mock guidelines, but at least it deals with code
that you can see and change in the controller.


More information about the rspec-users mailing list