Actually better then an exception On 8/23/07, Zach Dennis <[EMAIL PROTECTED]> wrote: > On 8/23/07, Daniel N <[EMAIL PROTECTED]> wrote: > > > > > > > > On 8/24/07, Courtenay <[EMAIL PROTECTED]> wrote: > > > Does this work? > > > > > > Image.stub!(:validates_uniqueness_of).and_return(true) > > > > > > > > > On 8/23/07, s.ross <[EMAIL PROTECTED]> wrote: > > > > I want to use mocks and stubs to test the controller, but am having > > > > trouble getting my validation not to trigger. Here's the code: > > > > > > > > # spec: > > > > > > > > Image.stub!(:find).and_return(@image) > > > > @image.should_receive(:save!).once.with(:any_args) > > > > put :update, :id => @image.id, :category_id => > > > > @category.id, :image => {:name => 'test', :image_number => 13554} > > > > > > > > #model > > > > > > > > validates_presence_of :name > > > > validates_uniqueness_of :name, :allow_nil => true > > > > > > > > # rspec output > > > > > > > > ActiveRecord::RecordInvalid in 'ImagesController should update a > > > > database record when it receives a PUT' > > > > Validation failed: Name has already been taken, Image number has > > > > already been taken > > > > > > > > > > > > It seems AR is not detecting that this is an edit/update that will > > > > not cause a uniqueness conflict. I believe the code in the model > > > > needs to remain in place because I don't want a user creating a name > > > > conflict by editing an existing name into one that already exists in > > > > the database. Any thoughts on how better to spec this? > > > > > > > > Thanks > > > > _______________________________________________ > > > > Why use a real image at all? I usually use mock_model on these and then > > stub/mock the specific calls in the controller method. This way your not > > testing the model at all. Just the controller. Of course, they can get > > pretty complex with all the stubbing etc. > > > > Image.stub!(:find).and_return(@image) > > @image.should_receive(:save!).once.with(:any_args) > > put :update, :id => @image.id, :category_id => > > @category.id, :image => {:name => 'test', :image_number => 13554} > > > > could become. > > > > @category = mock_model( Category, :id => 1 ) # Not sure where this one is > > used other than the call to put > > @image = mock_model( Image, :id => 2 ) > > @image.should_receive( :save! ).once.with( :any_args ).and_return( true ) > > Image.stub!( :find ).and_return( @image ) > > > > put :update, :id => @image.id, :category_id => > > @category.id, :image => {:name => 'test', :image_number => 13554} > > > > This way you're not reaching into the model to check your controller. > > You can even go as far as removing all of that ActiveRecord > interaction from your controller. > > @image = mock("image") > Image.should_receive(:update_image).with(@image) > put :update, :id => 1, :category_id => 2, :image => @image > > You would also want to test a failure case I'm sure (if you redirected...): > > Image.stub!(:update_image).and_raise(ActiveRecord::ActiveRecordError) > put :update, :id => 1, :category_id => 2, :image => @image > response.should be_redirect > response.should redirect_to(:action => "other_action") > > This keeps your controller a little cleaner and pushes down the > interaction of working with ActiveRecord models to a minimum. Now you > can put the code that actually handles an update in your model class > and your controller doesn't have to worry about how it is saved, it > either works or raises an exception,
If you are only using Category in the test then go with Daniel's first suggestion. If you only need a numeric id which represents a Category don't create a dummy mock that will only be used in your test. If your controller has to find a Category and an Image to update an image in your controller then I think my approach (minus the exception, use true/false return values instead on update_image) makes sense. Zach _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users