在教自己Ruby和Rails时,我目前正在建立一个基于Hartl tutorial的用户系统;此时的主要区别是我用Rspec / Capybara而不是TestUnit测试它。到目前为止,大多数事情都相当简单,但我在测试密码重置时遇到了这个问题。
当我手动测试密码重置时,它们完全按预期工作。因此,我很确定问题出在Rspec,Capybara和FactoryGirl之间。
失败的规范代码是我想访问忘记密码的链接:
# password_resets_spec.rb
visit(edit_password_reset_path(spec_user.reset_token, email: spec_user.email))
它给了我:
的ActionController :: UrlGenerationError: 没有路由匹配{:action =>" edit",:controller =>" password_resets",:email =>" john2@example.com", :format => nil,:id => nil}缺少必需的键:[:id]
密码重置是(部分)资源,其ID是用户的reset_token
。
spec_user
由FactoryGirl生成:
#password_resets_spec.rb
let(:spec_user){ FactoryGirl.create :user }
相关的:user
工厂没有设置reset_token
但是当我尝试使用的时候,重置表格没有正确设置令牌,并且没有匹配生成的摘要。以下是设置两者的代码:
# user.rb
def create_reset_digest
self.reset_token = User.new_token
update_attribute(:reset_digest, User.digest(reset_token))
update_attribute(:reset_sent_at, Time.zone.now)
end
我可以通过使用设置reset_token
的工厂来绕过上述错误,但是用于路径的令牌与保存的摘要不匹配,并且测试的下一步失败。 / p>
到目前为止,我的结论是我误解了虚拟属性的处理方式,因为在将摘要保存到数据库时,令牌是虚拟的。我怀疑我在规范中获得的reset_token
与我生成摘要的路径不同,不知怎的。
任何帮助了解此处的内容都将非常感谢! :)
答案 0 :(得分:1)
您收到路由错误,因为reset_token
没有值;在这种情况下你的身份。
您可以在工厂创建的对象上设置/分配虚拟属性。只需将值传递给工厂:
let(:spec_user){ FactoryGirl.create :user, reset_token: "some value"}
但是,对于您的用例,我猜测您还需要散列值在数据库中。 pasword_resets#edit
可能通过对传入的reset_token
进行哈希来查找用户记录。
所以,在您的规范中:
require 'spec_helper'
describe "PasswordResets" do
describe "#edit" do
it "looks up the user and provides a form to reset the password" do
# Generate the token in advance, so you can set the digest on the user
reset_token = User.new_token
# Create your user with the digest
spec_user = FactoryGirl.create(:user, reset_token: reset_token, reset_digest: User.digest(reset_token), reset_sent_at: Time.zone.now)
# Now visit path with an actual value for reset_tokeb
visit(edit_password_reset_path(spec_user.reset_token, email: spec_user.email))
end
end
end