我正在使用rspec测试我的模型的验证,并期待一条错误消息。但是,消息的确切文本可能会发生变化,所以我想要更宽容一些,只检查部分消息。
由于Spec :: Matchers :: include方法仅适用于字符串和集合,我目前正在使用此构造:
@user.errors[:password].any?{|m|m.match(/is too short/)}.should be_true
这可行,但对我来说似乎有点麻烦。是否有更好的(即更快或更像红宝石)的方法来检查数组是否包含正则表达式的字符串,或者可能是这样做的rspec匹配器?
答案 0 :(得分:16)
我建议你做
@user.errors[:password].to_s.should =~ /is too short/
只是因为它会在失败时给你一个更有帮助的错误。如果您使用be_any
,那么您会收到这样的消息......
Failure/Error: @user.errors[:password].should be_any{ |m| m =~ /is too short/}
expected any? to return true, got false
但是,如果您使用to_s
方法,那么您将获得以下内容:
Failure/Error: @user.errors[:password].to_s.should =~ /is too short/
expected: /is to short/
got: "[]" (using =~)
Diff:
@@ -1,2 +1,2 @@
-/is too short/
+"[]"
所以你可以看到失败的原因,而不必去挖掘它为什么会失败。
答案 1 :(得分:11)
将RSpec 3 expect
syntax与matchers composing一起使用:
匹配所有:
expect(@user.errors[:password]).to all(match /some message/)
匹配任何:
expect(@user.errors[:password]).to include(match /some message/)
expect(@user.errors[:password]).to include a_string_matching /some message/
答案 2 :(得分:9)
您可以将以下代码放在spec / support / custom_matchers.rb
中RSpec::Matchers.define :include_regex do |regex|
match do |actual|
actual.find { |str| str =~ regex }
end
end
现在您可以像这样使用它:
@user.errors.should include_regex(/is_too_short/)
并确保在spec / spec_helper.rb
中有类似的内容Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
答案 3 :(得分:8)
我认为它不会产生性能差异,但是更像RSpec的解决方案
@user.errors[:password].should be_any { |m| m =~ /is too short/ }
答案 4 :(得分:6)
以上两个答案都很好。但是,我会使用较新的Rspec expect
语法
@user.errors[:password].to_s.should =~ /is too short/
成为
expect(@user.errors[:password].to_s).to match(/is too short/)
此处有更多精彩信息:http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
答案 5 :(得分:3)
我对此的解决方案与@ muirbot相似。我使用自定义匹配器。但是,我使用真正的include
匹配器,但使用自定义匹配器作为参数进行扩充。在套件运行之前加载它(例如在spec / support / matchers.rb中,依次由spec / spec_helper.rb加载):
RSpec::Matchers.define(:a_string_matching) do |expected|
match do |actual|
actual =~ expected
end
end
然后你的期望可以这样写:
expect(@user.errors[:password]).to include(a_string_matching(/is too short/))
答案 6 :(得分:0)
只是另一种选择
@user.errors[:password].grep /is too short/