我使用简单的rails 4.1.0
app并且不使用设计。我正在测试应用程序控制器:
class ApplicationController < ActionController::Base
protected
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def signed_in?
!!current_user
end
helper_method :current_user, :signed_in?
def current_user=(user)
@current_user = user
session[:user_id] = user.try :id
end
# want to test this method
def authenticate_user!
render nothing: true, status: :unauthorized unless current_user
end
end
我遇到authenticate_user!
方法的问题。完整规范see here。方法规范:
describe 'authenticate_user!' do
context 'when user logged in' do
before { subject.send(:current_user=, create(:user)) }
it 'do nothing' do
expect(subject.send(:authenticate_user!)).to eq nil
end
end
context 'when user not logged in' do
controller do
before_action :authenticate_user!
def custom
render :text => 'response'
end
end
before do
subject.send(:current_user=, nil)
routes.draw { get 'custom' => 'anonymous#custom' }
get :custom
end
it 'returns unauthorized status' do
expect(response).to be_nil
end
# before do
# subject.send(:current_user=, nil)
# subject.send(:authenticate_user!)
# end
#
# it { render status: :unauthorized }
# it 'renders nothing' do
# expect(response).to be_nil
# end
end
end
当用户登录时它可以工作,但是当没有人时我尝试了2种方法:匿名控制器并且只是尝试调用此方法(在此处注释)。此外,我尝试从TestApplicationController
继承ApplicationController
,结果与匿名控制器相同。所以在这种情况下,接下来是错误:
Failure/Error: expect(response).to be_nil
expected: nil
got: #<ActionController::TestResponse:0x007fc03b158580 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007fc03b0e3938>, @stream=#<ActionDispatch::Response::Buffer:0x007fc03b08bc10 @response=#<ActionController::TestResponse:0x007fc03b158580 ...>, @buf=[" "], @closed=false>, @header={"X-Frame-Options"=>"SAMEORIGIN", "X-XSS-Protection"=>"1; mode=block", ....
因此尽管current_user
设置为nil并且控制器中有before_action :authenticate_user!
,它仍返回一些响应。我猜它忽略了它。
如果是
before do
subject.send(:current_user=, nil)
subject.send(:authenticate_user!)
end
it { render status: :unauthorized }
it 'renders nothing' do
expect(response).to be_nil
end
接下来是错误:
Failure/Error: subject.send(:authenticate_user!)
Module::DelegationError:
ActionController::RackDelegation#status= delegated to @_response.status=, but @_response is nil: #<ApplicationController:0x007fe854c592b8 @_action_has_layout=true, @_routes=nil, @_headers={"Content-Type"=>"text/html"}, @_status=200, @_request=#<ActionController::TestRequest:0x007fe854c78c80 @env={"rack.version"=>[1, 2], "rack.input"=>#<StringIO:0x007fe8544fbf98>, "rack.errors"=>#<StringIO:0x007fe8544f0080>, "rack.multithread"=>true, "rack.multiprocess"=>true, "rack.run_once"=>false, "REQUEST_METHOD"=>"GET", "SERVER_NAME"=>"example.org", "SERVER_PORT"=>"80",
没有设置状态的响应对象。
此外,在这种情况下:
controller do
# before_action :authenticate_user!
def custom
authenticate_user!
render :text => 'response'
end
end
错误不同:
Failure/Error: render :text => 'response'
AbstractController::DoubleRenderError:
Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
因此,渲染工作,但是2次,并且它会抛出错误。
我发现了很多种类似的测试,但主要是我设计的设计和方法。
感谢您的帮助。
答案 0 :(得分:3)
想通了。关键是 - 响应不应为零,因为动作回答了一些事情(渲染而不是空 - 空字符串)。而且render status: :unauthorized
错了,规格中没有渲染,它是来自控制器的一条线(我想知道它是如何出现的)。所以这个方法的正确规范:
context "when user not logged in" do
controller(ApplicationController) do
before_action :authenticate_user!
def custom
render text: 'response'
end
end
before do
subject.send(:current_user=, nil)
routes.draw { get 'custom' => 'anonymous#custom' }
get 'custom'
end
it { should respond_with :unauthorized }
it "returns nothing" do
expect(response.body).to be_blank
end
end