Проблема с RSpec с методом - PullRequest
       15

Проблема с RSpec с методом

0 голосов
/ 20 апреля 2010

Я кодировал следующую спецификацию:

  it "should call user.invite_friend" do

    user = mock_model(User, :id => 1)
    other_user = mock_model(User, :id => 2)
    User.stub!(:find).with(user.id).and_return(user)
    User.stub!(:find).with(other_user.id).and_return(other_user)
    user.should_receive(:invite_friend).with(other_user)

    post :invite, { :id => other_user.id }, {:user_id => user.id}

  end

Но я получаю следующую ошибку при запуске спецификации

NoMethodError in 'UsersController POST invite should call user.invite_friend'
undefined method `find' for # Class:0x86d6918 
app/controllers/users_controller.rb:144:in `invite'
./spec/controllers/users_controller_spec.rb:13:

В чем ошибка? Без .with работает просто отлично, но я хочу разные возвращаемые значения для разных аргументов метода-заглушки. Следующие действия контроллера могут иметь значение:

  def invite
    me.invite_friend(User.find params[:id])
    respond_to do |format|
      format.html { redirect_to user_path(params[:id]) }
    end
  end
  def me
    User.find(session[:user_id])
  end

1 Ответ

1 голос
/ 20 апреля 2010

Ошибка возникает из-за того, что заглушка «израсходована» при первом вызове find. Второй find не заглушен, поэтому вы получаете ошибку NoMethodError.

Кто-то может исправить меня, если я ошибаюсь, но .with оказывает странное влияние на заглушки, когда вы вызываете его более одного раза. Кажется, что Rspec ассоциирует каждое сообщение с тем же типом аргумента с одной заглушкой. Но другой тип аргумента эффективно создает другую заглушку. Так что в вашем случае вы можете исправить это, вызвав второй find со строкой:

User.stub!(:find).with(other_user.id.to_s).and_return(other_user)

, что вам повезло, потому что на самом деле контроллер ожидает строку в хэше params.

Это не отвечает на более широкий вопрос: как заглушить несколько вызовов методов с параметрами одного и того же типа аргумента? По моему опыту, вы не можете этого сделать.

Конечно, вы можете обойти это, не указав аргументы вообще. В вашем случае я бы сказал, что тестирование find само по себе не имеет отношения к вашему контроллеру - фактически вы проверяете, может ли ActiveRecord выполнить поиск в базе данных по первичному ключу, который уже хорошо протестирован. Так что, если вам нужно только заглушить ответы на find в правильном порядке, вы можете сделать это:

User.stub!(:find).and_return(user,other_user)

...