在rspec中更改挂钩之前的顺序

时间:2013-07-22 00:28:34

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

我有一个像这样的控制器规格:

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的结果不会被存根。

它试图这样做:

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。

有解决方案吗?

1 个答案:

答案 0 :(得分:6)

我强烈建议您不要在rspec中更改挂钩的顺序。这将使您的应用程序变得非标准,并且Rails基于标准并使事情按预期工作。

你所描述的一切“按照设计”。在块之前总是在内部块之前调用。

您认为“不太干净”的示例是执行控制器规范的标准方法。我实际上鼓励你这样做,以便它更易于维护/读取。它根本不是我的不洁净。

那就是说,有一些选择:

  1. 您可以使用方法。我不止一次有一个do_post或类似的方法
  2. 您可以使用懒惰初始化的let块。如果在先运行的块之前它依赖于其他,我会发现它是不可取的,但它是一个选项。
  3. 您可以定义subjecthttps://www.relishapp.com/rspec/rspec-core/v/2-6/docs/subject/explicit-subject