RSpec中无法看到ControllerMacros

我有一个Rails应用程序,我正在尝试测试它。 我使用devise登录。但是,当我想测试时,我遇到了一个问题:

Users/ender/Projects/ratingw/spec/controllers/widgets_controller_spec.rb:4:in `block in ': undefined local variable or method `login_user' for # (NameError) 

首先,我想说我读了这个设计正式教程 。

我的spec_helper.rb是:

  # This file is copied to spec/ when you run 'rails generate rspec:install' ENV["RAILS_ENV"] ||= 'test' require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' require 'rspec/autorun' require 'capybara/rspec' # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} RSpec.configure do |config| # ## Mock Framework # # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: # # config.mock_with :mocha # config.mock_with :flexmock # config.mock_with :rr OmniAuth.config.test_mode = true OmniAuth.config.mock_auth[:twitter] = { :provider => 'twitter', :uid => '123545' # etc. } OmniAuth.config.mock_auth[:twitter] = :invalid_credentials config.include Devise::TestHelpers, :type => :controller config.extend ControllerMacros, :type => :controller config.include RequestMacros, :type => :request # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{::Rails.root}/spec/fixtures" # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. config.use_transactional_fixtures = true # If true, the base class of anonymous controllers will be inferred # automatically. This will be the default behavior in future versions of # rspec-rails. config.infer_base_class_for_anonymous_controllers = false end module ::RSpec::Core class ExampleGroup include Capybara::DSL include Capybara::RSpecMatchers end end 

我还有一个controller_macros.rb,它位于支持文件中:

 module ControllerMacros def login_user before(:each) do @request.env["devise.mapping"] = Devise.mappings[:user] user = Factory(:user) #user.confirm! # or set a confirmed_at inside the factory. Only necessary if you are using the confirmable module sign_in user end end end 

最后,我的controller_spec文件是:

 require 'spec_helper' describe WidgetsController do login_user describe "User" do before(:each) do @current_user = mock_model(User, :id => 1) @widget = mock_model(Widget, :user_id => 1) Widget.stub!(:current_user).and_return(@current_user) Widget.stub!(:widgets).and_return(@widget) end it "should have a current_user" do subject.current_user.should_not be_nil redirect_to widgets_path end it "should not have a current_user" do redirect_to widgets_path new_user_session_path end end def mock_widget(stubs={}) @mock_widget ||= mock_model(Widget, stubs).as_null_object end describe "Get index" do it "should get all widgets " do Widget.stub(:all) { [mock_widget] } get :index assigns(:widgets) == @widgets end end describe "Post widget" do it "creates a new widget" do Widget.stub(:new).with({'these' => 'params'}) { mock_widget(:save => true) } post :create, :widget => {'these' => 'params'} assigns(:widget) == @widgets response.should redirect_to (edit_widget_path(@mock_widget)) end it "can not create a new widget" do Widget.stub(:new).with({'these' => 'params'}) { mock_widget(:save => false) } post :create, :widget => {'these' => 'params'} assigns(:widget) == @widgets redirect_to new_widget_path end end describe "Get widget" do it "shows exact widget via its uuid" do Widget.stub(:find).with("10") { mock_widget(:save => true) } get :show assigns(:widget) == @widget end end describe "Put widget" do it "updates the widget attributes" do Widget.stub(:find_by_uuid).with("6").and_return(mock_widget(:update_attributes => true)) mock_widget.should_receive(:update_attributes).with({'these' => 'params'}) put :update, :uuid => "6", :widget => {'these' => 'params'} response.should redirect_to (edit_widget_path(@mock_widget)) end it "can not update the widget attributes" do Widget.stub(:find_by_uuid).with("6").and_return(mock_widget(:update_attributes => false)) mock_widget.should_receive(:update_attributes).with({'these' => 'params'}) put :update, :uuid => "6", :widget => {'these' => 'params'} end end describe "delete destroy" do it "destroys the requested widget" do Widget.stub(:find_by_uuid).with("10").and_return(mock_widget) mock_widget.should_receive(:destroy) get :destroy, :uuid => "10" end end end 

我怎样才能解决这个问题? 问题是什么?

我想错误源于:

 config.extend ControllerMacros, :type => :controller 

你应该有:

 config.include ControllerMacros, :type => :controller