我有一个这样的控制器规格:
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这是一个简单的规范,但它不起作用,因为在块之前的上下文之前执行了块之前的描述。 因此,在调用create动作时, artist.save的结果artist.save被存根。
它试图这样做:
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。
有解决方案吗?
I have a controller spec like this :
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 endThis is a simple spec but It doesn't work because the describe's before block is executed before the context's before block. So, the result of artist.save is not stubed when the create action is called.
It tried to do this :
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 endI see the "2" before the "1". I'm not sure but I think it was working with previous versions.
I know, I can do this :
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 endBut I think it's less clean.
I found, on this page, http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/Hooks#before-instance_method than the order should be this :
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 groupIt's not the case on this example.
I'm not sure but I think it was working with older versions of rspec.
Is there a solution?
最满意答案
我强烈建议您不要在rspec中更改挂钩的顺序。 这将使您的应用程序不标准,Rails基于标准并使事情按预期工作。
你所描述的一切都“按照设计”。 块之前的外部总是在内部块之前调用。
您觉得“不太干净”的示例是执行控制器规范的标准方法。 我实际上鼓励你这样做,以便它更易于维护/读取。 它根本不是我的不洁净。
也就是说,有一些选择:
您可以使用方法。 我不止一次有一个do_post或类似的方法 你可以使用一个懒惰地初始化的let块。 如果它先依赖于其他块先运行,我会发现它是unlcean,但它是一个选项。 您可以定义subject 。 https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/subject/explicit-subjectI would strongly recommend against you changing the order of hooks in rspec. That will make your app non-standard and Rails is build on standards and having things work as expected.
Everything you're describing it "as designed". Outer before blocks are always called before inner blocks.
Your example that you feel is "less clean" is the standard way to do controller specs. I actually encourage you to do it this way so that it is more maintainable/readable. It does not look unclean to me at all.
That said, there are some options:
You can use a method. I have more than once had a method that was do_post or something similar You can use a let block which is initialized lazily. I would find it unlcean if it relied on other before blocks running first, but it's an option. You can define subject. https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/subject/explicit-subject更多推荐
发布评论