2010-09-09 1 views
0

Я пишу сценарий Rspec тот неудачу с:RSpec2 ошибка самым большим NEWB в Нью-Джерси :(| factory_girl, authlogic, rails3

(#<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 "[email protected]" 
    u.single_access_token "k3cFzLIQnZ4MHRmJvJzg" 
    u.id "37" 
end 
+0

Обновленный мой Rspec сценарий к советам всех ответов, но все-таки возвращаясь та же ошибка. – Trip

+0

Обновлена ​​специфика обнуления «current_user» и обновлена ​​ошибка выше. – Trip

ответ

2

Стандартные вспомогательные методы 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) 

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

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 
+0

Хорошо. Я соглашаюсь. Но почему update_attributes не проходит? – Trip

+0

Вы устанавливаете ожидание 'update_attributes' в переменной экземпляра' @ user', созданной в спецификации, но если ваш заглушка 'User.find' не возвращает эту ** точную ** переменную экземпляра, пользователь ее *. * возврат нет на это ожидание. Попробуйте добавить 'puts @ user.object_id' в контроллер и в спецификацию и посмотреть, отличаются ли они. –

+0

Не уверен, как одновременно получить инструкцию puts. Для контроллера я добавил puts @ user.obect_id, но где бы я поместил это в спецификацию? или как я должен сказать? он не возвращает оператор puts из i run spec. – Trip

2

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

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 фильтр перенаправил запрос.

+0

Штук очистил ошибку поиска. Делает так много смысла. Ошибка обновления завершилась неудачно, поэтому я переместил эти аутентифицированные примеры before() для каждого дочернего объявления (GET, PUT, POST, DELETE). Но он по-прежнему не работает во второй ошибке: '(# ). Update_attributes ({"username" => "Trippy"}) Ожидаемое: 1 раз получено: 0 раз – Trip

+0

Возможно, вы не получите точный хэш-парам, который вы ожидаете. Попробуйте изменить его на 'should_receive (: update_attributes) .with (anything()). And_return (true)' –

+0

А! Настолько счастлив, что знаю этот синтаксис. Но, увы, он возвращает ту же ошибку. Поэтому я предполагаю, что он не обновляется или не называется правильным. Просто не совсем понятно, почему. – Trip