【问题标题】:Convert old Rspec syntax into new syntax将旧 Rspec 语法转换为新语法
【发布时间】:2016-04-04 06:56:38
【问题描述】:

我正在使用APIonRails tutorial,他们有这个:

require 'spec_helper'

describe ApiConstraints do
  let(:api_constraints_v1) { ApiConstraints.new(version: 1) }
  let(:api_constraints_v2) { ApiConstraints.new(version: 2, default: true) }

  describe "matches?" do

    it "returns true when the version matches the 'Accept' header" do
      request = double(host: 'api.marketplace.dev',
                       headers: {"Accept" => "application/vnd.marketplace.v1"})
      api_constraints_v1.matches?(request).should be_true
    end

    it "returns the default version when 'default' option is specified" do
      request = double(host: 'api.marketplace.dev')
      api_constraints_v2.matches?(request).should be_true
    end
  end
end

举个例子,但我已经明白这是使用旧语法。

要将其转换为新语法,我正在尝试:

require 'rails_helper'

describe ApiConstraints do
  let(:api_constraints_v1) { ApiConstraints.new(version: 1) }
  let(:api_constraints_v2) { ApiConstraints.new(version: 2, default: true) }

  describe "matches?" do
    it "returns true when the version matches the 'Accept' header" do
      request = double(host: 'api.localhost:3000',
                headers: {"Accept" => "application/vnd.marketplace.v1"})
      expect(request).to match(api_constraints_v1)
    end

    it "returns the default version when 'default' option is specified" do
      request = double(host: 'api.localhost:3000')
      expect api_constraints_v2.matches?(request).to_be true
    end
  end

end

这是我得到的错误:

Failures:

  1) ApiConstraints matches? returns true when the version matches the 'Accept' header
     Failure/Error: expect(request).to match(api_constraints_v1)
       expected #<RSpec::Mocks::Double:0x3feeedaf60c4 @name=nil> to match #<ApiConstraints:0x007fddde50f9b0 @version=1, @default=nil>
       Diff:
       @@ -1,2 +1,2 @@
       -#<ApiConstraints:0x007fddde50f9b0 @default=nil, @version=1>
       +#<RSpec::Mocks::Double:0x3feeedaf60c4 @name=nil>

     # ./lib/spec/api_constraints_spec.rb:11:in `block (3 levels) in <top (required)>'

  2) ApiConstraints matches? returns the default version when 'default' option is specified
     Failure/Error: expect api_constraints_v2.matches?(request).to_be true
     NoMethodError:
       undefined method `to_be' for true:TrueClass
       Did you mean?  to_enum
                      to_s
     # ./lib/spec/api_constraints_spec.rb:16:in `block (3 levels) in <top (required)>'

Finished in 0.0045 seconds (files took 6.52 seconds to load)
2 examples, 2 failures

Failed examples:

rspec ./lib/spec/api_constraints_spec.rb:8 # ApiConstraints matches? returns true when the version matches the 'Accept' header
rspec ./lib/spec/api_constraints_spec.rb:14 # ApiConstraints matches? returns the default version when 'default' option is specified

这可能是什么原因造成的?

编辑 1

根据我的Gemfile.lock,这些是我的相关宝石的版本:

rspec (3.1.0)
  rspec-core (~> 3.1.0)
  rspec-expectations (~> 3.1.0)
  rspec-mocks (~> 3.1.0)
rspec-core (3.1.7)
  rspec-support (~> 3.1.0)
rspec-expectations (3.1.2)
  diff-lcs (>= 1.2.0, < 2.0)
  rspec-support (~> 3.1.0)
rspec-mocks (3.1.3)
  rspec-support (~> 3.1.0)
rspec-rails (3.1.0)
  actionpack (>= 3.0)
  activesupport (>= 3.0)
  railties (>= 3.0)
  rspec-core (~> 3.1.0)
  rspec-expectations (~> 3.1.0)
  rspec-mocks (~> 3.1.0)
  rspec-support (~> 3.1.0)
rspec-support (3.1.2)
rubyzip (1.2.0)
selenium-webdriver (2.53.0)
  childprocess (~> 0.5)
  rubyzip (~> 1.0)
  websocket (~> 1.0)
shellany (0.0.1)
shoulda (3.5.0)
  shoulda-context (~> 1.0, >= 1.0.1)
  shoulda-matchers (>= 1.4.1, < 3.0)
shoulda-context (1.2.1)
shoulda-matchers (2.8.0)
  activesupport (>= 3.0.0)

为了实现与原始代码相同的功能,我应该使用什么正确的新语法?

【问题讨论】:

  • expect request.to eq(api_constraints_v1) -> expect(request).to eq(api_constraints_v1)

标签: ruby-on-rails rspec rails-api ruby-on-rails-5


【解决方案1】:

在原来的测试中改变

api_constraints_v1.matches?(request).should be_true

expect(api_constraints_v1.matches?(request)).to be_truthy

expect(api_constraints_v1.matches?(request)).to be(true)

如果您希望只返回一个布尔值。

【讨论】:

  • 完美。这正是我一直在寻找的。非常感谢!
  • 为了转换很多旧的语法规范,我强烈推荐使用transpec
【解决方案2】:

改变

expect request.to eq(api_constraints_v1)

expect(request).to eq(api_constraints_v1)

和其他规范中的相同问题...

expect 是一种方法,您可以将期望发生的事情提供给它(即request)...

request 方法获得结果后 - 然后调用to...

您以前的方式...您首先request上调用to,然后然后将结果传递给expect.. . 即,对问题进行分组;)

【讨论】:

  • 好吧,我想真正的问题是:expect(request).to be(api_constraints_v1) 与:api_constraints_v1.matches?(request).should be_true 相同。我怀疑它是。旧语法期望的新语法版本是什么?
  • 添加括号:(api_constraints_v1.matches?(request)).should be_true(虽然不是旧应该的最佳实践)更清楚地显示了哪个部分给了should(因此哪个部分属于expect)。在这种情况下(假设您的 API 约束始终是正则表达式),您可以将其更改为 expect(request).to match(api_constraints_v1) 注意:您将始终使用带有 expect 语法的括号。它们不是可选的。
  • 这里的文档中有更多关于 match 匹配器的详细信息:relishapp.com/rspec/rspec-expectations/docs/built-in-matchers/…
  • 我喜欢你要去的地方 Taryn,但在这里并不能完全帮助我。例如,我尝试了你的后一个建议,这是我现在得到的错误:Failure/Error: expect(request).to match(api_constraints_v1) expected #&lt;RSpec::Mocks::Double:0x3fc4751b8504 @name=nil&gt; to match #&lt;ApiConstraints:0x007f88ea370148 @version=1, @default=nil&gt; Diff: @@ -1,2 +1,2 @@ -#&lt;ApiConstraints:0x007f88ea370148 @default=nil, @version=1&gt; +#&lt;RSpec::Mocks::Double:0x3fc4751b8504 @name=nil&gt; # /spec/api_constraints_spec.rb:11:in block (3 levels) in &lt;top (required)&gt;'
  • 是的,就像我说的......它只有在你的 api_constraints_v1 是一个正则表达式(或字符串)时才有效。就像matches? 一样;)
【解决方案3】:

我在我的rails-api-base 项目中使用了相同的ApiConstraints,当您尝试使用非默认版本的matches? 而不指定Accept 标头时,它会崩溃。

我添加了以下测试(崩溃):

it 'returns false when not default and no Accept header' do
  request = double(host: 'api.marketplace.dev')
  expect(api_constraints_v1.matches?(request)).to be false
end

我修复了ApiConstraints

def matches?(req)
  @default ||
    (req.respond_to?('headers') &&
     req.headers.key?('Accept') &&
     req.headers['Accept'].include?("application/vnd.marketplace.v#{@version}"))
end

希望对你有帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多