[英]Testing devise views with rspec
我已經生成了運行rails g devise:views
Devise rails g devise:views
,現在想測試它們。
這是我想出的:
require 'spec_helper'
describe "devise/sessions/new" do
before do
render
end
it "renders the form to log in" do
rendered.should have_selector("form", action: user_session_path, method: :post) do |form|
end
end
end
對於 render 語句,它給了我undefined local variable or method 'resource'
。 谷歌搜索后,我發現我應該添加
@user.should_receive(:resource).and_return(User.new)
在 render 語句之前 - 但它仍然給我同樣的錯誤,我不確定如何使用它。
我究竟做錯了什么? 謝謝你的幫助。
只是另一個想法,以防萬一有人遇到同樣的問題。 我不太喜歡向我的助手添加代碼只是為了讓測試可以通過,所以我最終在測試的 before 塊中添加了這段代碼:
before do
view.stub(:resource).and_return(User.new)
view.stub(:resource_name).and_return(:user)
view.stub(:devise_mapping).and_return(Devise.mappings[:user])
end
你知道嗎? 我在有人遇到類似問題的地方找到了這個答案。 解決方案是在您的應用程序助手中包含以下代碼:
def resource_name
:user
end
def resource
@resource ||= User.new
end
def devise_mapping
@devise_mapping ||= Devise.mappings[:user]
end
這是必要的,因為 devise 在其控制器中使用了某些輔助方法。 但是,如果我從我的規范訪問視圖,這些輔助方法不可用,因此我的測試失敗。 將這些方法放在應用程序助手中,使它們可以在整個應用程序中訪問,包括我的規范,並且確實通過了測試!
在rspec 中,有一個配置不允許您刪除未定義的方法。 使用rails 4,它甚至是標准行為:
# spec/spec_helper.rb
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
因此,最高投票的答案不適用於設計助手。 將verify_partial_doubles
更改為false
或使用實際幫助程序。
像 Mike Fogg 一樣,我不喜歡將幾個方法添加到我的 ApplicationController 只是為了讓這些視圖規范工作的想法。
我注意到我的 rspec 安裝有一個spec/mixins
目錄,所以我做了以下事情:
# spec/mixins/devise_helpers.rb
module DeviseHelpers
def resource_name
:user
end
def resource
@resource ||= User.new
end
def devise_mapping
@devise_mapping ||= Devise.mappings[:user]
end
end
然后包括在我的規范中:
# spec/views/devise/registrations/new.html.haml_spec.rb
require 'rails_helper'
include DeviseHelpers
describe 'devise/registrations/new.html.haml' do
it 'has a login link for existing users' do
render
expect(rendered).to have_link('Log in')
end
end
現在我可以將這些方法混合到任何需要它們的規范中。
我想做@MikeFogg 的解決方案——我在另一個視圖規范中做了類似的事情來處理 Pundit——但當然我遇到了@ChrisEdwards 指出的關於需要mocks.verify_partial_doubles = false
。
但是,我對在我的整個測試套件中關閉它沒有太大興趣,這是一個很好的檢查,“通常推薦”並且默認為 Rspec 4+。
我實際上首先在這里發布了一個解決方案,我在之前/之后的塊中重新配置了 RSpec,但是我遇到了一個非常非常簡單的方法來做到這一點,並且效果很好:
before(:each) do
without_partial_double_verification do
allow(view).to receive(:resource).and_return(Student.new)
allow(view).to receive(:resource_name).and_return(:student)
allow(view).to receive(:devise_mapping).and_return(Devise.mappings[:student])
end
# other before_each configuration here as needed
end
這自 2016 年以來一直存在,最初稱為without_verifying_partial_doubles
,但被重命名為當前的without_partial_double_verification
。 在我能看到的任何地方似乎都沒有記錄。
將@sixty4bit 的答案與這里的答案相結合,我想出了這個解決方案:
class DeviseHelpers < Module
def initialize(resource_name, resource_class)
@resource_name = resource_name
@resource_class = resource_class
end
def extended(base)
_resource_name = @resource_name
_resource_class = @resource_class
base.class_eval do
define_method :resource_name do
_resource_name
end
define_method :resource do
@resource ||= _resource_class.new
end
define_method :devise_mapping do
@devise_mapping ||= Devise.mappings[_resource_name]
end
end
end
end
這允許您通過在規范的頂部要求它來將它用於不同的資源:
require 'support/devise_helpers'
然后像這樣調用它:
before do
view.extend(DeviseHelpers.new(:customer, Customer))
end
對於 RSpec 4、Rails 6 和 Devise 4.7,我在這里的其他建議沒有成功,或者擔心對我的其他測試或生產代碼的影響。
allow(view).to receive(:current_user).and_return(user)
在我看來,規格最終對我有用,沒有任何其他配置更改。 (必須先定義user
。)
近年來,底層 gems/框架發生了有意義的變化,使這里的其他一些解決方案無效,這並非不可能。 更有可能是我錯誤地配置了 Devise、RSpec 和/或相關的幫助程序。
我確認current_user
填充在 rspec/rails/example/view_example_group.rb 中,但在render
期間返回nil
。 我在 view_example_group.rb 中找到了這條評論並關注了它:
# The instance of `ActionView::Base` that is used to render the template.
# Use this to stub methods _before_ calling `render`.
#
# describe "widgets/new.html.erb" do
# it "shows all the widgets" do
# view.stub(:foo) { "foo" }
# render
# # ...
# end
# end
def view
_view
end
https://github.com/rspec/rspec-rails/blob/main/lib/rspec/rails/example/view_example_group.rb
stub
語法已棄用,但view.stub(:current_user) { user }
也可以使用(目前)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.