【问题标题】:Use Rspec shared examples to test a Ruby class' attributes使用 Rspec 共享示例测试 Ruby 类的属性
【发布时间】:2018-05-01 13:27:40
【问题描述】:

尝试使用 Rspec 共享示例来测试两个类似 URL 的属性:

spec/entity_spec.rb

require 'entity'
require 'shared_examples/a_url'

describe Entity do

  # create valid subject
  subject { described_class.new(name: 'foobar') }

  context ':url attribute' do
    it_behaves_like "a URL"
  end

  context ':wikipedia_url attribute' do
    it_behaves_like "a URL"
  end

end

spec/shared_examples/a_url.rb

shared_examples_for('a URL') do |method|

    it "ensures that :#{method} does not exceed 255 characters" do
      subject.send(:method=, 'http://' + '@' * 256)
      expect(subject).to_not be_valid
    end

    it "ensures that :#{method} do not accept other schemes" do
      subject.send(:method=, 'ftp://foobar.com')
      expect(subject).to_not be_valid
    end

    it "ensures that :#{method} accepts http://" do
      subject.send(:method=, 'http://foobar.com')
      expect(subject).to be_valid
    end

    it "ensures that :#{method} accepts https://" do
      subject.send(:method=, 'https://foobar.com')
      expect(subject).to be_valid
    end

end

显然我需要将:url:wikipedia_url 属性的引用发送到共享示例,但是如何?

【问题讨论】:

    标签: ruby rspec rspec3


    【解决方案1】:

    您的共享示例块接受一个参数method,但您没有将参数传递给它。但是,你非常接近。只需更改:

    context ':url attribute' do
      it_behaves_like "a URL", :url
    end
    

    现在我们将:url 符号作为method 传递给共享示例。然后你需要将你对:method=(这将失败,因为它实际上是subject.method=)的引用更改为subject.send("#{method}=", value),以便我们实际上调用方法url=。例如

    it "ensures that :#{method} does not exceed 255 characters" do
      subject.send("#{method}=", 'http://' + '@' * 256)
      expect(subject).to_not be_valid
    end
    

    话虽如此,我建议将局部变量的名称从 method 更改为其他名称(甚至可能是 method_name),以避免混淆 method() 方法和您的局部变量 method

    Full Example

    【讨论】:

      【解决方案2】:

      您可以“使用块为共享组提供上下文”,如 here 所述。

      require "set"
      
      RSpec.shared_examples "a collection object" do
        describe "<<" do
          it "adds objects to the end of the collection" do
            collection << 1
            collection << 2
            expect(collection.to_a).to match_array([1, 2])
          end
        end
      end
      
      RSpec.describe Array do
        it_behaves_like "a collection object" do
          let(:collection) { Array.new }
        end
      end
      
      RSpec.describe Set do
        it_behaves_like "a collection object" do
          let(:collection) { Set.new }
        end
      end
      

      【讨论】:

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