Ошибка RSpec2 от самого большого новичка в Нью-Джерси :( | factory_girl, authlogic, rails3 - PullRequest
0 голосов
/ 09 сентября 2010

Я пишу сценарий rspec, который завершается ошибкой:

 (#<User:0x1056904f0>).update_attributes(#<RSpec::Mocks::ArgumentMatchers::AnyArgMatcher:0x105623648>)
     expected: 1 time
     received: 0 times

users_controller_spec.rb:

describe "Authenticated examples" do
  before(:each) do
    activate_authlogic
    @user = Factory.create(:valid_user)
    UserSession.create(@user)
  end

describe "PUT update" do
    it "updates the requested user" do
      User.stub!(:current_user).and_return(@user)
      @user.should_receive(:update_attributes).with(anything()).and_return(true)
      put :update, :id => @user , :current_user => {'email' => 'Trippy'}
      puts "Spec Object Id : " + "#{@user.object_id}"
 end

users_controller.rb:

def update
  @user = current_user
  puts "Controller Object ID is : " + "#{@user.object_id}"

  respond_to do |format|
    if @user.update_attributes(params[:user])
      format.html { redirect_to(root_url, :notice => 'Successfully updated profile.') }
      format.xml  { head :ok }
    else
      format.html { render :action => "edit" }
      format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
    end
  end
end

user.rb - фабрики

Factory.define :valid_user, :class => User do |u|
  u.username "Trippy"
  u.password "password"
  u.password_confirmation "password"
  u.email "elephant@gmail.com"
  u.single_access_token "k3cFzLIQnZ4MHRmJvJzg"
  u.id "37"
end

Ответы [ 2 ]

2 голосов
/ 10 сентября 2010

Стандартные вспомогательные методы Authlogic, такие как current_user, не вызывают User.find напрямую. Я считаю, что это делает current_user_session.user, где current_user_session звонит UserSession.find, так что вы не звоните User.find напрямую. Вы могли бы сделать некоторую причудливую цепную заглушку там, но я предлагаю просто добавить это к вашей спецификации контроллера вместо того, что вы в настоящее время заглушаете:

stub!(:current_user).and_return(@user)

В RSpec2 вам, возможно, придется сделать

controller.stub!(:current_user).and_return(@user)

Редактировать: Это должен быть весь ваш файл спецификации:

describe "Authenticated examples" do
  before(:each) do
    activate_authlogic
    @user = Factory.create(:valid_user)
    UserSession.create(@user)
  end

describe "PUT update" do

  describe "with valid params" do
    it "updates the requested user" do
      stub!(:current_user).and_return(@user)
      @user.should_receive(:update_attributes).with(anything()).and_return(true)
      put :update, :id => @user , :current_user => {'email' => 'Trippy'}
    end
 end
2 голосов
/ 09 сентября 2010

Я думаю, вы путаете заглушки с ожиданиями сообщений.Строка

User.should_receive(:find)

указывает Rspec ожидать, что пользовательская модель получит сообщение о поиске.Принимая во внимание, что:

User.stub!(:find)

заменяет метод поиска, чтобы тест мог пройти.В вашем примере вы проверяете, успешно ли вызывается update_attributes, так что это должно быть именно там, где идет ожидание сообщения, а задача всего остального кода тестирования - просто установить предварительные условия.

Попробуйте заменить эту строку на:

User.stub!(:find).and_return(@user)

Обратите внимание, что find возвращает объект, а не только его идентификатор.Также обратите внимание, что заглушка find здесь служит только для ускорения процесса.Как написано, пример успешно проходит через should_receive(:find) и , что происходит, потому что вы используете фабрики для создания пользователей в тестовой базе данных.Вы можете снять заглушку, и тест все равно будет работать, но ценой попадания в базу данных.

Еще один совет: если вы пытаетесь выяснить, почему тест контроллера не работает, иногда этополезно знать, не блокируется ли это before фильтрами.Вы можете проверить это с помощью:

controller.should_receive(:update)

Если это не удастся, действие update не будет достигнуто, возможно, потому что фильтр before перенаправил запрос.

...