首页 > 解决方案 > RSpec Rails - subject + assigns as one liner?

问题描述

I am struggling with the following RSpec. Why does this works:

   it 'GET articles#new creates new instance of Article' do
    get :new
    expect(assigns[:article]).to be_a(Article)
  end

And neither of those do (found some examples with different brackets and that's why I decided to check both possibilities)

  subject { get :new }
  it { expect(assigns[:article]).to be_a(Article) }
  it { expect(assigns(:article)).to be_a(Article) }

I am getting this error:

 Failure/Error: it { expect(assigns(:article)).to be_a(Article) }
   expected nil to be a kind of Article(id: integer, title: string, body: string, author_id: integer, created_at: datetime, updated_at: datetime)
 # ./spec/controllers/articles_controller_spec.rb:35:in `block (4 levels) in <top (required)>'

I don't know how to retrieve "article" from the subject...

I have also tried some various combinations of "subject" and "assigns" inside it { ... }, but I couldn't get it working.

I'd rather keep it clean and store it in one line only :)

BTW: Do you have any other habits of writing Specs for controllers? (I already check for response 200)

标签: ruby-on-railsrubyrspec

解决方案


根据文档,控制器规格:

允许您在每个示例中模拟单个 http 请求,然后指定预期结果,例如:

  • 在控制器中分配以与视图共享的实例变量

这就是为什么您必须在块内运行请求(如get :newit以返回正确的输出。

如果您将请求定义为规范的主题(关于subject 此处的精度),则需要在it块内运行主题:

subject { get :new }

it 'GET articles#new creates new instance of Article' do
  subject
  expect(assigns[:article]).to be_a(Article)
end

推荐阅读