使用rspec测试设计视图

我已经生成了运行rails g devise:views Devise的视图,现在想测试它们。

这就是我想出的:

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

whaddya知道吗? 我找到了这个答案 ,其中有人有类似的问题。 解决方案是在应用程序助手中包含以下代码:

 def resource_name :user end def resource @resource ||= User.new end def devise_mapping @devise_mapping ||= Devise.mappings[:user] end 

这是必要的,因为设计在其控制器中使用某些辅助方法。 但是,如果我从我的规范中访问视图,则这些辅助方法不可用,因此我的测试失败了。 将这些方法放在应用程序帮助程序中可以在整个应用程序中访问它们,包括我的规范,实际上测试通过了!

像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 

现在我可以将这些方法混合到任何需要它们的规范中。

rspec中有一个配置,它不允许你删除未定义的方法。 使用rails 4,它甚至是标准行为:

 # spec/spec_helper.rb config.mock_with :rspec do |mocks| mocks.verify_partial_doubles = true end 

因此,投票率最高的答案与设计助手无关。 将verify_partial_doubles更改为false或使用实际帮助程序。

将@ 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