[rspec-users] [JRuby] simulating a java exception in a spec

Lenny Marks lenny at aps.org
Tue Aug 23 14:27:14 EDT 2011

> On Aug 22, 2011, at 5:50 PM, Lenny Marks wrote:
>> JRuby 1.6.2
>> rspec-core (2.6.4)
>> rspec-expectations (2.6.0)
>> rspec-mocks (2.6.0)
>> rspec-rails (2.6.1)
>> I'm sure this has more to do with the way JRuby wraps Java exceptions but I figured I'd post here in case anyone here has any insight or pointers. In the context of writing a spec for a model like thing that wraps legacy Java code, I found myself attempting to stub a method on a Java Exception rescued in the implementation.
>> eg.
>> describe '#valid?' do
>> ....
>> it 'adds validation exceptions raised by service to #errors' do
>>      ve = ValidationException #a java exception
>>      ve.stub(:localized_message).and_return('a bunch of errors')
>>      service.stub(:validateTaskForSave).and_raise(ve)
>>      subject.valid?
>>      subject.errors.should == ['a bunch of errors']
>> end

> it 'adds validation exceptions raised by service to #errors' do
>     ve = ValidationException #a java exception
>     ve.stub(:localized_message).and_return('a bunch of errors')
>    ....
> Just clarifying, but did you mean
>    ve = ValidationException.new
> I tried replicating your spec but with java.lang.RuntimeException
> instead of ValidationException and I got
>   exception class/object expected
> because raise expects an instance of the exception, not the exception
> class. Am I missing something?
> Best,
> Sidu.
> http://c42.in
> http://blog.sidu.in

You have to raise an exception instance, not the class of the exception as is typical with Ruby exceptions. Check out the "boiled down" example below to reproduce. 

>> the above example fails because the :localize_message stub is ignored and instead the real implementation receives the message. I know this typically screams typo but not in this case. Here is a more boiled down version:
>> specify 'rescued exception message should be "bar" because I stubbed it' do
>>      begin
>>        e = Java::java.lang.NullPointerException.new('foo')
>>        e.stub(:message).and_return('bar')
>>        raise e
>>      rescue Java::java.lang.NullPointerException => e
>>        e.message.should == 'bar'
>>      end
>> end
>> Failure/Error: e.message.should == 'bar'
>>       expected: "bar"
>>            got: "foo" (using ==)
>> That seemed odd to me but maybe moot anyway since in reality I would be need to rescue a NativeException masquerading as my target exception.
>> e.g. This code
>> def valid?
>>    begin
>>      service.validateTaskForSave(task)
>>    rescue ValidationException => e
>>      puts "rescued exception: #{e.class.name}"
>>      .....
>> prints "rescued exception: NativeException"  when hit through the console.

The more I think about this, the more I wish it was different(more explicit) in JRuby. IMO, the above is very unintuitive (i.e. if I rescue a specific exception class then I would expect the exception instance to be an instance of that class). Any attempt to reference a custom method on a rescued java exception results in "undefined method".

rescue MyJavaException => e
  # e.some_method  "undefined method"
  e.cause.some_method # need to unwrap

AFAICT, the JRuby wiki makes no mention of this behavior ( https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby ). Of course that's more suited for the JRuby mailing list, but if it is just a matter of filling in the docs then there should still be an easy way to simulate such an exception with #and_raise such that custom methods on the exception can be stubbed. No?? 


>> So how would one simulate a NativeException if needed (i.e. you want to stub methods on it)?
>> -lenny
>> _______________________________________________
>> rspec-users mailing list
>> rspec-users at rubyforge.org
>> http://rubyforge.org/mailman/listinfo/rspec-users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20110823/9e98e0ad/attachment.html>

More information about the rspec-users mailing list