29

I'm trying to test a Rails controller branch that is triggered when the model method raises an error.

def my_controller_method
  @my_object = MyObject.find(params[:id])

  begin
    result = @my_object.my_model_method(params)
  rescue Exceptions::CustomError => e
    flash.now[:error] = e.message       
    redirect_to my_object_path(@my_object) and return
  end

  # ... rest irrelevant
end

How can I get a Minitest stub to raise this Error?

it 'should show redirect on custom error' do
  my_object = FactoryGirl.create(:my_object)

  # stub my_model_method to raise Exceptions::CustomError here

  post :my_controller_method, :id => my_object.to_param
  assert_response :redirect
  assert_redirected_to my_object_path(my_object)
  flash[:error].wont_be_nil
end
s01ipsist
  • 3,022
  • 2
  • 32
  • 36

2 Answers2

27
require "minitest/autorun"

class MyModel
  def my_method; end
end

class TestRaiseException < MiniTest::Unit::TestCase
  def test_raise_exception
    model = MyModel.new
    raises_exception = -> { raise ArgumentError.new }
    model.stub :my_method, raises_exception do
      assert_raises(ArgumentError) { model.my_method }
    end
  end
end
Panic
  • 2,229
  • 23
  • 25
  • 14
    Pro tip: If the method you are stubbing to raise an exception has parameters, you need to include those in your lambda: raises_exception = -> (a,b,c) { raise ArgumentError.new }. – Brad Jul 23 '15 at 15:38
20

One way to do this is to use Mocha, which Rails loads by default.

it 'should show redirect on custom error' do
  my_object = FactoryGirl.create(:my_object)

  # stub my_model_method to raise Exceptions::CustomError here
  MyObject.any_instance.expects(:my_model_method).raises(Exceptions::CustomError)

  post :my_controller_method, :id => my_object.to_param
  assert_response :redirect
  assert_redirected_to my_object_path(my_object)
  flash[:error].wont_be_nil
end
blowmage
  • 8,854
  • 2
  • 35
  • 40
  • 4
    If the exception has arguments, you have to provide the instance: ```MyObject.any_instance.expects(:my_model_method).raises(Exceptions::CustomError.new(some_arg))``` – Tony Dec 18 '15 at 18:20
  • 1
    @Tony you saved my day! This comment should get many many votes – p.matsinopoulos Mar 21 '18 at 08:06
  • You can also stub the expectation directly on the instance, instead of stubbing "any_instance" of MyObject. Just call the expects on the my_object instance directly. – Andrea Salicetti Mar 03 '21 at 16:47