Reputation: 46675
I'm writing a Ruby library - call it module MyLibrary
- which depends upon a data parser. The parser is specific to the library, but may need to be swapped out for a different parser at a later date, so it makes sense to have it be a class nested in MyLibrary
- class MyLibrary::Parser
.
MyLibrary
exposes a few exception types to the client, and the Parser
may hit situations where it wants to raise these exceptions (and MyLibrary
is happy to pass them through). So I have the following arrangement:
my_library.rb:
require 'parser'
module MyLibrary
class SomeException < RuntimeError
end
def self.do_it
parser = Parser.new
parser.parse_it
end
end
parser.rb
module MyLibrary
class Parser
def parse_it
if bad_stuff
raise SomeException, "Argh"
end
end
end
end
Now, I want to unit-test Parser
using rspec.
parser_spec.rb
require 'parser'
RSpec.describe Parser do
it 'raises when bad stuff happens' do
expect { Parser.new.parse_it }.to raise_error(MyLibrary::SomeException)
end
end
But because I'm unit-testing the Parser
and my_library.rb hasn't been required in, SomeException
isn't defined.
What's my best method for providing SomeException
within Parser
's spec? Or am I going about this in completely the wrong way?
Upvotes: 1
Views: 67
Reputation: 1784
I think there are 2 things you could consider.
Building on maxple's comment, unless you have a specific reason for it, the SomeException
class could just be defined in parser.rb
. That class is the one raising the error, the spec test would work, and anyone requiring that file would have access to that exception. Since you don't even reference it in my_library.rb
it seems like it would be fine. Another behavioral reason that supports this approach is if the error is a "Parsing" error, the exception name should reflect that and the Parser
is the class that should own that. If the MyLibrary
class is just forwarding any exception along, it doesn't matter what it is and it shouldn't be defined there.
If you want to keep the exception defined in my_library.rb
, then I would suggest using a spec_helper.rb
file, that lives in your spec
folder, to load your full library. This is usually done by requiring your top level lib/my_library.rb
file. Rspec commonly adds your top level lib folder to the ruby include path for just this purpose. Then each and every spec test file you write should require 'spec_helper'
. In my experience this is probably the most idiomatic way to load all common dependencies for unit testing in rspec.
Upvotes: 2
Reputation: 274
I haven't done much in rspec but wouldn't it help if you move the require 'parser'
line from my_library.rb
to parser.rb
? The way I see it it's the Parser that needs that exception not the other way around.
Like I said my knowledge in this case is limited but I hope that will help, if not good luck in the search! :)
Upvotes: -1