On Fri, May 4, 2012 at 7:14 PM, Patrick J. Collins
<[email protected]> wrote:
> So, I have an action like this:
>
> def destroy
> if purchase.user == current_user && purchase.refund
> redirect_to purchase
> else
> flash[:error] = t("purchases.refund.failure")
> render :show
> end
> end
>
> ... I wanted a controller test to verify the following:
>
> 1. It's the correct user
> 2. The refund was successful
> 3. User is redirected
>
> ...
>
> Initially, I thought this would go something like this:
>
> describe "#destroy" do
> let(:purchase) { create_purchase }
>
> it "refunds the buyer" do
> subject.stubs(:current_user).returns purchase.user
> purchase.stubs(:refund).returns true
> put :destroy, { :id => purchase.id }
> response.should be_redirect
> end
> end
>
> WRONG!!!!!!!!!
>
> Obviously, that is not cool because purchase.stubs(:refund) will not be the
> right object in the context of the controller...... So since my controller
> is actually doing the following:
>
> def destroy
> if purchase.user # etc...
> end
>
> private
>
> def purchase
> @purchase ||= Purchase.find(params[:id])
> end
>
> I could do:
>
> subject.stubs(:purchase).returns(purchase)
>
> .. However, now that kind of defeats the purpose of put :destroy, { :id =>
> purchase.id }...
>
> So I didn't really like that-- I am no longer verifying it's the right record,
> so maybe the things I wanted to test were actually:
>
> 1. It finds the purchase
> 2. It's the correct user
> 3. The refund was successful
> 4. User is redirected
>
> ........
>
> So I ended up making my test do:
>
> describe "#destroy" do
> let(:purchase) { create_purchase }
>
> def do_destroy
> put :destroy, { :id => purchase.id }
> end
>
> it "refunds the buyer" do
> subject.stubs(:current_user).returns purchase.user
> Purchase.any_instance.stubs(:refund).returns true
> do_destroy
> response.should be_redirect
> end
> subject.stubs(:current_user).returns purchase.user
> Purchase.any_instance.stubs(:refund).returns true
>
> do_destroy
> response.should redirect_to purchase.offer
> end
>
> it "does not refund the buyer when it fails" do
> subject.stubs(:current_user).returns purchase.user
> Purchase.any_instance.stubs(:refund).returns false
>
> put :destroy, :id => purchase.id
> response.should_not be_redirect
> end
>
> it "does not refund the buyer when it's the wrong user" do
> subject.stubs(:current_user).returns create_user
> Purchase.any_instance.expects(:refund).never
>
> do_destroy
> response.should_not be_redirect
> end
> end
>
> But then I heard the voice of an old friend in my head, saying (with a long
> trailing echo) "any_instance is terrible practice.. never use it!"
>
> So I am curious if anyone has suggestions on how this might be improved?
Instead of any_instance you could stub the interaction with
Purchase.find in your spec:
Purchase.stubs(:find).with(purchase.id).returns purchase
HTH,
Zach
>
> Thank you.
>
> Patrick J. Collins
> http://collinatorstudios.com
> _______________________________________________
> rspec-users mailing list
> [email protected]
> http://rubyforge.org/mailman/listinfo/rspec-users
--
--
@zachdennis
http://www.continuousthinking.com
http://www.mutuallyhuman.com
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users