【问题标题】:Rails/Rspec - How to use multiple it without redoing workRails/Rspec - 如何在不重做工作的情况下使用多个它
【发布时间】:2021-04-06 07:57:54
【问题描述】:

多次我想通过同一个操作检查多个事情,比如说我想做一个 PUT 并查看请求是否返回 200 以及响应值是否包含一些值以及 ActiveRecord 模型是否已更新。

在下一个示例中,我尝试使用 before,但它在每个 it 之前运行。

context "with valid params" do
  before do
    put my_url
  end

  it "returns a 200 response" do
    expect(response).to have_http_status(200)
  end

  it "updates the right values" do
    expect(my_model.min_area).to eq(111)
    expect(my_model.max_area).to eq(222)
  end

  it "dont update a param if it is not sent" do
    expect(my_model.budget).to eq(333)
  end
end

我希望 before 块只运行 1 次,并且每次都验证它的内容。 通过这种方法,我可以清楚地看到失败时失败的原因。

其他方法是删除每个 it 并且只有 1 个喜欢:

context "with valid params" do
  it "updates all" do
    put my_url

    expect(response).to have_http_status(200)
    expect(my_model.min_area).to eq(111)
    expect(my_model.max_area).to eq(222)
    expect(my_model.budget).to eq(333)
  end
end

但是这种方法并不能在失败时立即告诉我失败的原因。

如何在不必为每个 it 块执行 before 的情况下做到这一点?

【问题讨论】:

  • 如果您正在访问外部服务,并且您的主要目标是性能/效率,您还可以考虑使用像 vcr 这样的 gem,它首先记录然后在以后出现时“重播”答案。这将允许您像以前一样编写测试,并且仍然可以从性能提升中受益。

标签: ruby-on-rails ruby unit-testing rspec rspec-rails


【解决方案1】:

你可以这样做而不是before(:context)

context "with valid params" do
  it "updates all" do
    put my_url

    expect(response).to have_http_status(200)
    expect(my_model.min_area).to eq(111)
    expect(my_model.max_area).to eq(222)
    expect(my_model.budget).to eq(333)
  end
end

但你需要告诉 RSpec 给aggregate failures

你可以it per block

context "with valid params", :aggregate_failures do
  it "updates all" do
    put my_url

    expect(response).to have_http_status(200)
    expect(my_model.min_area).to eq(111)
    expect(my_model.max_area).to eq(222)
    expect(my_model.budget).to eq(333)
  end
end

或者设置globally for your project,其他选项都可以,选你最喜欢的吧。

【讨论】:

    【解决方案2】:

    您可能正在寻找before(:context)

    before(:context) do
      put my_url
    end
    
    context "with valid params" do
      it "returns a 200 response" do
        expect(response).to have_http_status(200)
      end
    
      it "updates the right values" do
        expect(my_model.min_area).to eq(111)
        expect(my_model.max_area).to eq(222)
      end
    
      it "dont update a param if it is not sent" do
        expect(my_model.budget).to eq(333)
      end
    end
    

    请注意,有些人可能会争辩说使用before(:context)anti-pattern

    【讨论】:

    • 谢谢!似乎这种方法已被弃用,它已从rspec 3 中删除,而且我无法从那里访问let...我仍然不明白为什么
    猜你喜欢
    • 2012-08-31
    • 1970-01-01
    • 2018-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 2016-12-13
    • 1970-01-01
    相关资源
    最近更新 更多