我有一个这样的 Controller 规范:
describe "#create" do
before { post 'create', params }
context "when the artist is valid" do
before { allow(artist).to receive(:save).and_return(true) }
it { expect(page).to redirect_to(root_path) }
it { expect(notifier).to have_received(:notify) }
end
end
这是一个简单的规范,但它不起作用,因为 describe 的 before block 在 context 的 before block 之前执行。所以,
artist.save
的结果调用 create 操作时不会被 stub 。它试图这样做:
describe "first describe" do
before { puts 2 }
describe "second describe" do
before { puts 1 }
it "simple spec" do
expect(1).to eq 1
end
end
end
我在“1”之前看到“2”。我不确定,但我认为它适用于以前的版本。
我知道,我可以这样做:
describe "#create" do
context "when the artist is valid" do
before { allow(artist).to receive(:save).and_return(true) }
it "redirect to the root path" do
post 'create', params
expect(page).to redirect_to(root_path)
end
it "do notifications" do
post :create, params
expect(notifier).to have_received(:notify)
end
end
end
但我认为它不太干净。
我发现,在这个页面上,http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/Hooks#before-instance_method比顺序应该是这样的:
before(:suite) # declared in RSpec.configure
before(:all) # declared in RSpec.configure
before(:all) # declared in a parent group
before(:all) # declared in the current group
before(:each) # declared in RSpec.configure
before(:each) # declared in a parent group
before(:each) # declared in the current group
在这个例子中不是这样。
我不确定,但我认为它适用于旧版本的 rspec。
有解决办法吗?
最佳答案
我强烈建议您不要更改 rspec 中的钩子(Hook)顺序。这将使您的应用程序非标准,并且 Rails 是基于标准构建的,并且可以按预期工作。
您将其描述为“按设计”的所有内容。外部前 block 总是在内部 block 之前调用。
您觉得“不太干净”的示例是执行 Controller 规范的标准方法。我实际上鼓励您这样做,以便它更易于维护/可读。在我看来,它一点也不脏。
也就是说,有一些选择:
do_post
或类似的东西let
延迟初始化的 block 。如果它依赖于其他先运行的 block ,我会发现它是 unlcean,但它是一个选项。 subject
. https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/subject/explicit-subject 关于ruby-on-rails - 更改 rspec 中的 before 钩子(Hook)的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17778368/