Ruby on Rails-这是消除RSpec中重复代码的好方法吗?

时间:2018-08-02 01:53:24

标签: ruby-on-rails rspec rspec-rails

我写了这段代码来测试控制器更新功能。 写了一种消除重复代码的方法。 这是一种明确的方法吗?

users_controller_spec.rb

context 'Update failed' do
  def render_edit
    user.reload
    expect(response.status).to eq(200)
  end
  it 'Name is nil' do
    put :update, params: { id: user.id, user: { name: '' } }
    render_edit
  end
  it 'Email is exist' do
    create(:user, email: 'user@gmail.com')
    put :update, params: { id: user.id, user: { email: 'user@gmail.com' } }
    render_edit
  end
  it 'Email is nil' do
    put :update, params: { id: user.id, user: { email: '' } }
    render_edit
  end
  it 'Password must be at least 8 characters' do
    put :update, params: { id: user.id, user: { password: '1234567', password_confirmation: '1234567' } }
    render_edit
  end
  it 'Passwords do not match' do
    put :update, params: { id: user.id, user: { password: '1234567890', password_confirmation: '123456789' } }
    render_edit
  end
end

我当时正在考虑使用after(:each)。但是看起来有点逻辑上的联系。 或使用循环替换参数。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

您可以使用注释中建议的共享示例,但是有一种更简单的方法。

context 'Update failed' do
  before do
    put :update, params: params
    user.reload # I'm not sure why you need this
  end

  subject { response } 

  context 'Name is nil' do
    let(:params} { {id: user.id, user: { name: '' }} }
    it { is_expected.to be_success }
  end

  context 'Email exists' do
    let(:params) { { id: user.id, user: { email: 'user@gmail.com' } }
    let(:user) { create(:user, email: 'user@gmail.com') }
    it { is_expected.to be_success }
  end
  # and so on
end

我使用的主要符文是-使每种情况下的变化显而易见。因此,与其重新定义put ...,不如将其提取为let并根据上下文进行定义。

be_success是rspec魔术的一部分,无论您在哪里使用be_something匹配器,它都会尝试使用something?方法并检查其是否正确,即。

expect(foo).to be_empty? == expect(foo.empty?).to eq(true)

如果您不希望这样的话

subject { response.status }
# and later
is_expected.to eq 200 

is_expected.to仅仅是expect(subject).to

的简写