7

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

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 块在 context 的 before 块之前执行。因此,artist.save调用 create 操作时,结果不会被存根。

它试图这样做:

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。

有解决办法吗?

4

1 回答 1

7

我强烈建议您不要更改 rspec 中的钩子顺序。这将使您的应用程序非标准,而 Rails 是基于标准构建的,并且可以按预期工作。

您将其描述为“按设计”的所有内容。外部前块总是在内部块之前调用。

您觉得“不太干净”的示例是执行控制器规格的标准方法。我实际上鼓励您这样做,以便它更易于维护/可读。在我看来,它一点也不脏。

也就是说,有一些选择:

  1. 你可以使用一种方法。我不止一次有过do_post类似的方法
  2. 您可以使用let延迟初始化的块。如果它依赖于其他先运行的块,我会发现它是 unlcean,但它是一个选项。
  3. 您可以定义subject. https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/subject/explicit-subject
于 2013-07-22T01:39:01.210 回答