Я пытаюсь написать тест запроса, который утверждает, что в макете приложения отображаются правильные ссылки в зависимости от того, вошел ли пользователь в систему или нет.FWIW, я использую Devise для проверки подлинности.
Вот моя спецификация:
require 'spec_helper'
require 'devise/test_helpers'
describe "Layout Links" do
context "the home page" do
context "session controls" do
context "for an authenticated user" do
before do
# I know these should all operate in isolation, but I
# want to make sure the user is explicitly logged out
visit destroy_user_session_path
@user = Factory(:user, :password => "Asd123", :password_confirmation => "Asd123")
@user.confirm!
# I tried adding this per the Devise wiki, but no change
@request.env["devise.mapping"] = Devise.mappings[:user]
# Now log a new user in
visit new_user_session_path
fill_in "Email", :with => @user.email
fill_in "Password", :with => "Asd123"
click_button "Sign in"
get '/'
end
it "should not have a link to the sign in page" do
response.should_not have_selector(
'#session a',
:href => new_user_session_path
)
end
it "should not have a link to registration page" do
response.should_not have_selector(
'#session a',
:href => new_user_registration_path
)
end
it "should have a link to the edit profile page" do
response.should have_selector(
'#session a',
:content => "My Profile",
:href => edit_user_registration_path
)
end
it "should have a link to sign out page" do
response.should have_selector(
'#session a',
:content => "Logout",
:href => destroy_user_session_path
)
end
end # context "for an authenticated user"
end # context "session controls"
end
end
Первый тест пройден, но последние три не пройдены с ошибкой
Failure/Error: @user = Factory(:user, :password => "Asd123", :password_confirmation => "Asd123")
RuntimeError:
Could not find a valid mapping for #<User id: xxx, ...>
Я искал в вики Devise, группе Google и результатах поиска причину, но все, что я нашел, - это оставшиеся без ответа вопросы или предложения по установке config.include Devise::TestHelpers, :type => :controller
, но это относится только к тестам контроллера, а не к запросу теста.
Обновление
Я выполнил еще несколько проблем и не могу понять, что в конечном итоге вызывает проблему.Взгляните на следующий код.
Во-первых, для некоторого контекста здесь приведено объявление фабрики пользователей.Он отлично работает в модульных тестах.
# spec/factories.rb
Factory.define :user do |f|
f.email { Faker::Internet.email }
f.email_confirmation { |f| f.email }
f.password "AbcD3fG"
f.password_confirmation "AbcD3fG"
f.remember_me { (Random.new.rand(0..1) == 1) ? true : false }
end
Теперь рассмотрим следующий интеграционный тест
# spec/requests/user_links_spec.rb
require "spec_helper"
describe "User Links" do
before(:each) do
# This doesn't trigger the problem
# @user = nil
# This doesn't trigger the problem
# @user = User.new
# This doesn't trigger the problem
# @user = User.create(
# :email => "foo@bar.co",
# :email_confirmation => "foo@bar.co",
# :password => "asdf1234",
# :password_confirmation => "asdf1234"
# )
# This doesn't trigger the problem
# @user = User.new
# @user.email = Faker::Internet.email
# @user.email_confirmation = @user.email
# @user.password = "AbcD3fG"
# @user.password_confirmation = "AbcD3fG"
# @user.remember_me = (Random.new.rand(0..1) == 1) ? true : false
# @user.save!
# This triggers the problem!
@user = Factory(:user)
# This doesn't trigger the same problem, but it raises a ActiveRecord::AssociationTypeMismatch error instead. Still no idea why. It was working fine before in other request tests.
# @user = Factory(:brand)
end
context "when using `@user = Factory(:user)` in the setup: " do
2.times do |i|
it "this should pass on the 1st iteration, but not the 2nd (iteration ##{i+1})" do
# This doesn't trigger an error
true.should_not eql(false)
end
it "this should pass on the 1st iteration, but trigger the error that causes all successive test cases to fail (iteration ##{i+1})" do
# Every test case after this will be borken!
get '/'
end
it "this will fail on all iterations (iteration ##{i+1})" do
# This will now trigger an error
true.should_not eql(false)
end
end
end
end
Если мы закомментируем или заменим бит get '/'
на что-то еще (или ничего навсе), все тесты выполняются нормально.
Итак, я не знаю, является ли это проблемой factory_girl (я склонен сомневаться в этом, поскольку я могу использовать фабрики пользователей в другом месте без проблем) или проблему Devise(Я начал получать эти ошибки после настройки этого драгоценного камня в моем приложении, но у меня также был только один другой тест запроса, который работал нормально, но теперь получаю эту ошибку AssociationTypeMismatch; корреляция ≠ причинность ...) или проблему RSpec или какую-то другуюстранный конфликт с драгоценными камнями.