4

我是一个 RSpec 新手,但我真的很喜欢编写测试是多么容易,并且随着我学习 RSpec 的新功能,我会不断地重构它们以使其更干净。所以,最初,我有以下内容:

describe Account do
  context "when new" do
    let(:account) { Account.new }
    subject { account }

    it "should have account attributes" do
      subject.account_attributes.should_not be_nil
    end
  end
end

然后我了解了该its方法,因此我尝试将其重写为:

describe Account do
  context "when new" do
    let(:account) { Account.new }
    subject { account }

    its(:account_attributes, "should not be nil") do
      should_not be_nil
    end
  end
end

由于its不接受 2 个参数而失败,但删除消息效果很好。问题是,如果测试失败,失败示例部分下的消息只会显示

rspec ./spec/models/account_spec.rb:23 # Account when new account_attributes

这并没有太大帮助。

那么,有没有办法将消息传递给its,或者更好的是,让它自动输出一个理智的消息?

4

3 回答 3

3

您可以定义一个 RSpec 自定义匹配器:

RSpec::Matchers.define :have_account_attributes do
  match do |actual|
    actual.account_attributes.should_not be_nil
  end
  failure_message_for_should do
    "expected account_attributes to be present, got nil"
  end
end

describe Account do
  it { should have_account_attributes }
end
于 2012-09-18T02:21:35.843 回答
1

你也可以写:its(:account_attributes) { should_not be_nil }

https://www.relishapp.com/rspec/rspec-core/v/2-14/docs/subject/attribute-of-subject

请注意,随着 rspec 3 的发布,“its”将从 rspec-core 提取到 gem 中。

于 2013-06-01T19:51:21.340 回答
0

看起来一个相对简单的猴子补丁可以满足您的需求。

查看您正在使用的 rspec-core gem 版本的来源。我在 2.10.1。在文件中lib/rspec/core/subject.rb,我看到了its定义的方法。

这是我的修补版本 - 我更改了def行和之后的行。

注意 - 这很可能是特定于版本的!从您的版本中复制方法并像我一样修改它。请注意,如果 rspec-core 开发人员对代码进行了重大重组,则补丁可能需要非常不同。

module RSpec
  module Core
    module Subject
      module ExampleGroupMethods
        # accept an optional description to append
        def its(attribute, desc=nil, &block)
          describe(desc ? attribute.inspect + " #{desc}" : attribute) do
            example do
              self.class.class_eval do
                define_method(:subject) do
                  if defined?(@_subject)
                    @_subject
                  else
                    @_subject = Array === attribute ? super()[*attribute] : _nested_attribute(super(), attribute)
                  end
                end
              end
              instance_eval(&block)
            end
          end
        end
      end
    end
  end
end

那个补丁可能会放在你的spec_helper.rb.

现在的用法:

its("foo", "is not nil") do
  should_not be_nil
end

失败时输出:

rspec ./attrib_example_spec.rb:10 # attr example "foo" is not nil 

如果省略第二个参数,则行为将与未修补的方法一样。

于 2012-09-14T17:58:52.333 回答