[rspec-users] Where do a set the description on a should satisfy.

David Chelimsky dchelimsky at gmail.com
Mon Sep 27 09:14:01 EDT 2010


On Sep 27, 2010, at 8:12 AM, David Chelimsky wrote:

> 
> On Sep 27, 2010, at 8:05 AM, GregD wrote:
> 
>> On Sep 26, 6:37 pm, David Chelimsky <dchelim... at gmail.com> wrote:
>>> On Sep 24, 2010, at 1:29 PM, GregD wrote:
>>>> Hi all,
>>> 
>>>> Newbie here and I'm using rspec with jruby to test a java class, but
>>>> this is more of a rspec question.
>>> 
>>>> I have a java HashMap object and want to make sure a key exists.  I
>>>> have this as my test:
>>> 
>>>>   context :toHashMap do
>>>>     subject { @var_list.toHashMap }
>>> 
>>>>     it { should satisfy{|a| a.contains_key?(var1) } }
>>>>     it { should satisfy{|a| a.contains_key?(var2) } }
>>>>     it { should satisfy{|a| a.contains_key?(var3) } }
>>>>   end
>>> 
>>>> @var_list is set to another java object that has a method toHashMap
>>>> that returns
>>>> a HashMap.  var1, var2 and var3 are set using let(:var1), etc.  If the
>>>> one of
>>>> these fails, I get this telling me that I need to supply a description
>>>> method:
>>> 
>>>> 'Java::LibraryLanguage::XmlVariableList when added duplicate variables
>>>> with different values toHashMap should When you call a matcher in an
>>>> example without a String, like this:
>>> 
>>>> specify { object.should matcher }
>>> 
>>>> or this:
>>> 
>>>> it { should matcher }
>>> 
>>>> RSpec expects the matcher to have a #description method. You should
>>>> either
>>>> add a String to the example this matcher is being used in, or give it
>>>> a
>>>> description method. Then you won't have to suffer this lengthy warning
>>>> again.
>>>> ' FAILED
>>>> expected {var01=2, var02=this-is-a-string} to satisfy block
>>>> <<<<<<<
>>> 
>>>> I'd like to put 'contain the key <blah>' in place of 'When you call a
>>>> matcher in
>>>> an example without a String'
>>> 
>>>> Where do I put that string?  I thought I could just do:
>>> 
>>>> it "should contain the key #{var1}" { should satisify{|a|
>>>> a.contains_key?(var1)
>>>> } }
>>> 
>>>> But, the loading complains on that.  Where can a put a custom
>>>> description into
>>>> this code (easily/polite way).
>>> 
>>> Congratulations - you're apparently the first person to ever use the satisfy matcher with an implicit subject, and have uncovered a bug!
>>> 
>>> http://github.com/rspec/rspec-expectations/issues/issue/20
>>> 
>>> I'd recommend not using that satisfy matcher for this case though, as it's really intended to be more of a last resort, and you can do much better with a custom matcher:
>>> 
>>>  RSpec::Matchers.define :contain_key do |key|
>>>    match do |subject|
>>>      subject.contains_key?(key)
>>>    end
>>>  end
>>> 
>>> Then you can say:
>>> 
>>>  context :toHashMap do
>>>    subject { @var_list.toHashMap }
>>> 
>>>    it { should contain_key(var1) }
>>>    it { should contain_key(var2) }
>>>    it { should contain_key(var3) }
>>>  end
>>> 
>>> More info on custom matchers:http://github.com/rspec/rspec-expectations/blob/master/features/match...
>>> 
>>> HTH,
>>> David
> 
>> That helped a lot and I see it is a better/more polite 1-liner-way.
>> Do you recommend that these custom matchers probably need to go into a
>> spec helper for standard java classes and included since contains_key?
>> (key) maps to the java HashMap method containsKey(key)?  Do I put
>> these in a ruby module to be included?
> 
> [I moved your responses to the bottom. Please use bottom or inline posting rather than top posting. ]
> 
> The convention is to have a line like this in spec/spec_helper.rb:
> 
>  Dir["./spec/support/**/*.rb"].each {|f| require f}
> 
> And then keep matchers and other support files under ./spec/support/

re: how to include them: yes, in a module:

# in spec/support/custom_matchers.rb
module CustomMatchers
  ...
end

# in spec/spec_helper.rb
RSpec.configure do |c|
  c.include CustomMatchers
end

Make sense?


More information about the rspec-users mailing list