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

David Chelimsky dchelimsky at gmail.com
Mon Sep 27 09:12:33 EDT 2010


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/

HTH,
David


More information about the rspec-users mailing list