0

我想断言数组包含的元素类,我尝试了以下方法:

这不起作用,但它看起来不错且可读:

["String", :symbol, Object.new].should =~ [an_instance_of(String), an_instance_of(Symbol), an_instance_of(Object)]

但给了我以下错误:

Failure/Error: ["String", :symbol, Object.new].should =~ [an_instance_of(String), an_instance_of(Symbol), an_instance_of(Object)]
   expected collection contained:  [#<RSpec::Mocks::ArgumentMatchers::InstanceOf:0x007f9e6a33dbe0 @klass=String>, #<RSpec::Mocks::ArgumentMatchers::InstanceOf:0x007f9e6a33dbb8 @klass=Symbol>, #<RSpec::Mocks::ArgumentMatchers::InstanceOf:0x007f9e6a33db68 @klass=Object>]
   actual collection contained:    ["String", :symbol, #<Object:0x007f9e6a33dca8>]
   the extra elements were:        ["String", :symbol, #<Object:0x007f9e6a33dca8>]

请注意,没有缺少元素。

这可行,但看起来很老套:

["String", :symbol, Object.new].collect{|x| x.class}.should =~ [String, Symbol,Object]
  1. 有没有更好的方法来断言同样的事情?
  2. 为什么第一种方式没有缺失元素?
4

2 回答 2

3

您可以使用&:class而不是块,

["String",:symbol,Object.new].map(&:class).should =~ [String,Symbol,Object]

产生相同但更具可读性。

另外,我使用map了该collect方法的简短别名。

于 2013-01-08T23:21:45.510 回答
2

第二部分的答案取决于您的断言“请注意,没有遗漏的元素”。缺少元素

这个:

expected collection contained:  [#<RSpec::Mocks::ArgumentMatchers::InstanceOf:0x007f9e6a33dbe0 @klass=String>, #<RSpec::Mocks::ArgumentMatchers::InstanceOf:0x007f9e6a33dbb8 @klass=Symbol>, #<RSpec::Mocks::ArgumentMatchers::InstanceOf:0x007f9e6a33db68 @klass=Object>]

与此不同:

the extra elements were:        ["String", :symbol, #<Object:0x007f9e6a33dca8>]

第一个包含类实例的模拟对象,第二个包含类的实例。不应该以这种instance_of方式使用匹配器,您会这样做吗?

["String", :symbol, Object.new].should =~ [respond_to(:gsub), respond_to(:intern), respond_to(:object_id)]

这是没有意义的,因为您应该测试数组 或者数组的内容每个都具有某种属性。您所做的是将两个测试混合在一起,这样做会导致两者都出现问题。

subject { instance }
["String", :symbol, Object.new].each do |thing|
  let(:instance) { thing.class }
    if instance.class == String
      it{ should respond_to(:gsub) }
    else #...

更像这样的东西,但我认为这是一种代码/设计气味——为什么你会在同一个数组中有这么不同的东西?很难规范、测试和处理。

于 2013-01-09T18:49:33.003 回答