RSpec - 测试控制器中的实例变量

时间:2016-12-13 15:22:55

标签: ruby-on-rails ruby rspec

我有一个新操作,可以创建一个圆圈并将当前父级分配为其管理员:

def new
  return redirect_to(root_path) unless parent
  @circle = Circle.new(administrator: parent)
end

我试图测试管理员ID是否已正确设置,并且已经写出了我的测试:

context 'with a parent signed in' do
  before do
    sign_in parent
    allow(controller).to receive(:circle).and_return(circle)
    allow(Circle).to receive(:new).and_return(circle)
  end

  it 'builds a new circle with the current parent as administrator' do
    get :new
    expect(@circle.administrator).to equal(parent)
  end
end

这显然会导致错误@circlenil。如何访问尚未从控制器测试中保存的新对象?我猜这是允许/允许的各种各样,但正如我所说,我所有的搜索到目前为止都没有产生。

2 个答案:

答案 0 :(得分:2)

你正在接近这个问题。测试控制器的行为。不是它的实现。

如果这是遗留应用程序,您可以使用assigns访问控制器的@circle实例变量:

context 'with a parent signed in' do
  before do
    sign_in parent
  end
  it 'builds a new circle with the current parent as administrator' do
    get :new
    expect(assigns(:circle).administrator).to equal(parent)
  end
end

But Rails 5 removes assigns在新项目中不鼓励使用它。 相反,我会使用功能规范并实际测试创建圆的步骤:

require 'rails_helper'

RSpec.feature 'Circles' do

  let(:parent) { create(:parent) }

  context "a guest user" do
    scenario "can not create circles" do
      visit new_circle_path
      expect(page).to have_content 'Please sign in'
    end
  end

  context "when signed in" do
    background do
      login_as parent
    end

    scenario "can create circles" do
       visit new_circle_path
       fill_in 'name', with: 'Test Circle'
       expect do
         click_button 'Create circle'
       end.to change(parent.circles, :count).by(+1)
       expect(page).to have_content 'Test Circle'
    end 
  end
end

答案 1 :(得分:0)

您可以使用assigns

expect(assigns(:circle).administrator).to eq parent

但是,请注意,对于rails 5,这已被弃用。检查控制器中分配的实例变量的合理性是太脆弱和特定于实现。

建议的替代方法是测试副作用(例如,如果这实际上是持久保存到db)或进行全功能测试。