gpt4 book ai didi

ruby-on-rails - 如何在 Controller 规范中添加类似作用域的方法

转载 作者:数据小太阳 更新时间:2023-10-29 08:31:51 25 4
gpt4 key购买 nike

这个问题的另一个变体:How to test controller scopes in DRY style?

我在 Controller 中有很多作用域:

class SettingsController < ApplicationController
before_filter :authenticate, :require_admin
before_filter :navigation, only: [:show, :edit]

def show
flash[:notice] = I18n.t(:thank_you_for_your_subscription) if params[:p]
end

def edit
render_not_found and return unless %w(username password).include?(params[:section])

@section = params[:section]
end
...

所以,我在 Controller 规范(用于操作)中有很多类似的方法。典型的 Controller 规范是:

describe SettingsController do
let!(:user) { Factory(:user) }

describe "GET #show" do
def do_action
get :show
end

it_requires_sign_in
it_requires_admin
it_specifies_navigation_with 'settings'

it "should set a flash message when the 'p' param is set" do
sign_in_as user
do_action
flash[:notice].should_not be_nil
end
end

describe "GET #edit" do
def do_action options = {}
get :edit, options.merge(format: 'rjs')
end

it_requires_sign_in
it_requires_admin
it_specifies_navigation_with 'settings'

context "when singed in" do
before { sign_in_as user }

it "should render 404 if no section is provided" do
do_action
response.code.should == '404'
end
end
end
end

但是 it_requires_sign_in 方法有下一个表示:

def it_requires_sign_in
it "should require sign in" do
send do_action
response.should redirect_to(sign_in_path)
end
end

导航:

def it_specifies_navigation_with(name)
it "specifies navigation with '#{name}'" do
controller.should receive(:current_navigation).with(name)
sign_in_as user
do_action
end
end

因此,它使用描述部分的方法。是否有可能在某种范围内指定我要检查或不检查的方法(操作),例如:

describe SettingsController do
requires_sign_in # every action (inner describe parts)
requires_admin
specifies_navigation_with only: [:show, :edit]

let!(:user) { Factory(:user) }

describe "GET #show" do
def do_action
get :show
end

it "should set a flash message when the 'p' param is set" do
sign_in_as user
do_action
flash[:notice].should_not be_nil
end
end
...

主要问题是在精确范围内调用精确方法do_action(我的意思是描述 Action 部分)。

最佳答案

我不会集中精力干太多。规范是一种文档。因此我认为规范应该是:

  • 可读性:尝试过于干燥可能会导致规范难以阅读和理解。
  • 易于更改:您很可能需要更改 Controller 中的操作。这应该可以在不更改其他操作规范的情况下实现。

因此,我认为在规范中重复一遍是可以的。

如果我必须指定 Controller 的那部分,我将从定义一个共享示例开始:

# shared example for authenticated admins 
RSpec.shared_examples 'an action only for authenticated admins' do
describe 'before_filter :authenticate' do
context 'with an user signed in' do
before { sign_in_as(user) }

it 'does not redirect' do
expect(response).to_not redirect_to(sign_in_path)
end

end

context 'without an user' do
it 'redirects to the sign in page' do
expect(response).to redirect_to(sign_in_path)
end
end
end

describe 'before_filter :require_admin' do
before { sign_in_as(user) }

context 'when user is an admin' do
before { allow(user).to receive(:admin?).and_return(true) }

it 'does something' do
# check something
end
end

context 'when user is not an admin' do
before { allow(user).to receive(:admin?).and_return(false) }

it 'does something other' do
# check something other
end
end
end

describe 'before_filter :navigation' do
before do
allow(controller).to receive(:current_navigation).and_return_original
allow(user).to receive(:admin?).and_return(true)
sign_in_as(user)
end

it 'sets the current navigation name' do
response
expect(controller).to have_received(:current_navigation).with(navigation_name)
end
end
end

参见 documentation有关如何使用共享示例的更多示例。

在 Controller 规范本身中,您会注意到我对准备示例和不同上下文的每个步骤都非常明确。此外,我更喜欢新的 expect(...).to 语法,而不是旧的 (...).should 语法。

describe SettingsController do
let(:user) { Factory(:user, :admin => true) }

describe 'GET show' do
subject(:response) { get :show }

it_behaves_like 'an action only for authenticated admins' do
let(:navigation_name) { 'settings' }
end

context 'with an admin signed in' do
before { sign_in_as(user) }

it 'shows a flash message' do
response
expect(flash[:notice]).to_not be_nil
end
end
end

describe 'GET edit' do
subject(:response) { get :edit, { format: 'rjs' } }

it_behaves_like 'an action only for authenticated admins' do
let(:navigation_name) { 'settings' }
end

context 'with an admin signed in' do
before { sign_in_as(user) }

it 'shows a flash message' do
expect(response.code).to eq('404')
end
end
end
end

关于ruby-on-rails - 如何在 Controller 规范中添加类似作用域的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25653045/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com