簡體   English   中英

使用 rspec 測試設計視圖

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM