I've been working with the Mechanize gem a lot recently and would like to incorporate some tests to ensure I am catching the proper errors. What is the proper way to test error handling?
This is my basic method:
def get(str)
url = format_url(str)
#puts "sending GET request to: #{url}"
sleep(0.1)
@page = Mechanize.new do |a|
a.user_agent_alias = 'Mac Safari'
a.open_timeout = 7
a.read_timeout = 7
a.idle_timeout = 7
a.redirect_ok = true
end.get(url)
rescue Mechanize::ResponseCodeError => e
puts "#{'Response Error:'.red} #{e}"
rescue SocketError => e
puts "#{'Socket Error:'.red} #{e}"
rescue Net::OpenTimeout => e
puts "#{'Connection Timeout:'.red} #{e}"
rescue Errno::ETIMEDOUT => e
puts "#{'Connection Timeout:'.red} #{e}"
rescue Net::HTTP::Persistent::Error
puts "#{'Connection Timeout:'.red} read timeout, too many resets."
end
And this is the start to tests for handling errors:
class TestErrorHandling < Mechanize::TestCase
context 'Example when sending a GET request' do
should 'rescue error and return nil' do
assert_equal nil, Example.get('http://localhost/pagethatdoesntexist')
end
end
end
Am I heading in the correct direction? Any insight and/or resources welcome.
Sort of. You shouldn't test dependent libraries again in your application. It's enough to catch the Net::HTTP::Persistent::Error without ensuring the underlying functionality is working. Well written gems should provide their own tests, and you should be able to access those tests as needed by testing that gem (Mechanize, for example).
You could mock for those errors, but you should be judicious. Here is some code to mock an SMTP connection
class Mock
require 'net/smtp'
def initialize( options )
@options = options
@username = options[:username]
@password = options[:password]
options[:port] ? @port = options[:port] : @port = 25
@helo_domain = options[:helo_domain]
@from_addr = options[:from_address]
@from_domain = options[:from_domain]
#Mock object for SMTP connections
mock_config = {}
mock_config[:address] = options[:server]
mock_config[:port] = @port
@connection = RSpec::instance_double(Net::SMTP, mock_config)
allow(@connection).to receive(:start).and_yield(@connection)
allow(@connection).to receive(:send_message).and_return(true)
allow(@connection).to receive(:started?).and_return(true)
allow(@connection).to receive(:finish).and_return(true)
end
#more stuff here
end
I don't see you testing for any custom errors which would make more sense here. For example, you might test for url-unfriendly characters in your parameter and rescue from that. In that case, your test would offer something explicit.
expect(get("???.net")).to raise_error(CustomError)