How to test adding line to error log by causing rescue statement in rspec - ruby

I have a this Foo class.
class Foo
def open_url
Net::HTTP.start("google.com") do |http|
# Do Something
end
rescue Exception => e
File.open("error.txt","a+"){|f| f.puts e.message }
end
end
And I want to test by this Rspec.
require_relative 'foo'
describe Foo do
describe "#open_url" do
it "should put error log if connection fails" do
Net::HTTP.stub(:start).and_return(Exception)
# Check if a line to error.txt is added.
end
end
end
How can I check if a line is inserted to error.txt?

You could read the file you are actually writing
describe Foo do
describe "#open_url" do
it "should put error log if connection fails" do
Net::HTTP.stub(:start).and_raise
Foo.open_url
file = File.open("error.txt", "r")
# ...
end
end
end
An alternative would be to check that the file is opened: something along the lines of this
File.should_receive(:open).with("error.txt", "a+", {|f| f.puts e.message })

Related

RSpec why is before(:each) never executed?

I have this simple code
require 'json'
module Html
class JsonHelper
attr_accessor :path
def initialize(path)
#path = path
end
def add(data)
old = JSON.parse(File.read(path))
merged = old.merge(data)
File.write(path, merged.to_json)
end
end
end
and this spec (reduced as much as I could while still working)
require 'html/helpers/json_helper'
describe Html::JsonHelper do
let(:path) { "/test/data.json" }
subject { described_class.new(path) }
describe "#add(data)" do
before(:each) do
allow(File).to receive(:write).with(path, anything) do |path, data|
#saved_string = data
#saved_json = JSON.parse(data)
end
subject.add(new_data)
end
let(:new_data) { { oldestIndex: 100 } }
let(:old_data) { {"test" => 'testing', "old" => 50} }
def stub_old_json
allow(File).to receive(:read).with(path).and_return(#data_before.to_json)
end
context "when given data is not present" do
before(:each) do
puts "HERE"
binding.pry
#data_before = old_data
stub_old_json
end
it "adds data" do
expect(#saved_json).to include("oldestIndex" => 100)
end
it "doesn't change old data" do
expect(#saved_json).to include(old_data)
end
end
end
end
HERE never gets printed and binding.pry doesn't stop execution and tests fail with message No such file or directory # rb_sysopen - /test/data.json
This all means that before(:each) never gets executed.
Why?
How to fix it?
It does not print desired message because it fails at the first before block. Rspec doc about execution order
It fails because you provided an absolute path, so it is checking /test/data.json
Either use relative path to the test ie. ../data.json (just guessing),
or full path.
In case of rails:
Rails.root.join('path_to_folder_with_data_json', 'data.json')

Ruby code not executed after method call

Code is not executed (puts "hey") in the harvest method after the call to searchEmails(page). I'm probably missing something simple with Ruby because I'm just getting back into it.
def searchEmails(page_to_search)
begin
html = #agent.get(url).search('html').to_s
mail = html.scan(/['.'\w|-]*#+[a-z]+[.]+\w{2,}/).map.to_a
base = page_to_search.uri.to_s.split("//", 2).last.split("/", 2).first
mail.each{|e| #file.puts e+";"+base unless e.include? "example.com" or e.include? "email.com" or e.include? "domain.com" or e.include? "company.com" or e.length < 9 or e[0] == "#"}
end
end
def harvest(url)
begin
page = #agent.get(url)
searchEmails(page)
puts "hey"
rescue Exception
end
end
url="www.example.com"
harvest(url)
#agent.get(url) will fail with a bad url or network outage.
The problem in your code could be written as follows:
def do_something
begin
raise
puts "I will never get here!"
rescue
end
end
Since you can't get rid of the raise, you need to do something inside the rescue (most likely log it):
begin
#agent.get(url)
# ...
rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError,
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
Net::ProtocolError => e
log(e.message, e.callback)
end

Ruby Rspec message expectations for a caught exception

Is there any way with Rspec to set an expectation for an exception that gets caught? I want to verify that MyException gets raised, but since I am catching the exception Rspec does not appear to know it ever happened.
begin
if success
do good stuff
else
raise MyException.new()
end
rescue MyException => e
clean up
end
I've tried a few things like the following without success. MyException.should_receive(:new) and
Kernel.should_receive(:raise).with(MyException)
You could test the behavior of the rescue block instead of checking for the exception:
class Test
def my_method
if success
# do good stuff
else
raise MyException.new()
end
rescue MyException => e
clean_up
end
end
describe Test do
it "should clean up when unsuccessful" do
subject.stub(:success) { false }
subject.should_receive(:clean_up)
subject.my_method
end
end
I figured out how to do what I needed.
class MyClass
def my_method
begin
if success
do good stuff
else
raise MyException.new
end
rescue MyException => e
# clean up
end
end
end
describe MyClass do
it "Expects caught exception" do
my_instance = MyClass.new()
my_instance.should_receive(:raise).with(any_instance_of(MyException))
my_instance.my_method()
end
end
Thanks for your other suggestions.
I would do as below:
RSpec.describe "matching error message with string" do
it "matches the error message" do
expect { raise StandardError, 'this message exactly'}.
to raise_error('this message exactly')
end
end
copied verbatim from Rspec Documentation

No such file or directory error in service

I am a newbie to ruby and got stuck into one of the issues with the windows service I created (code is below). When the service runs, I get an error in test log that there is notsuch file or directory and it does not find any path to the logs with name QaTaTestExe.log.xml. This is the error I see in file.
***Daemon failure 2013-07-28 16:29:28 -0400 err=No such file or directory
However when I tried the code (which is after while running? ) in separate class it works. Am I missing anything in my configuration since the error is regarding Daemon?
LOG_FILE = 'C:\\test.log'
require "rubygems"
begin
require 'win32/daemon'
include Win32
class Daemon
def service_main
while running?
testresultpath = "Z:/Windows 2008 R2 - Exchange 2010 - Search"
file_path s =[]
Find.find(testresultpath) do |path|
file_paths << path if path =~ /.*\QaTaTestExe.log.xml$/
File.open("c:\\test.log", "a"){ |f| f.puts(path)}
end
sleep 30
File.open("c:\\test.log", "a"){ |f| f.puts "Service is running #{Time.now}" }
end
end
def service_stop
File.open("c:\\test.log", "a"){ |f| f.puts "***Service stopped #{Time.now}" }
exit!
end
end
Daemon.mainloop
rescue Exception => err
File.open(LOG_FILE,'a+'){ |f| f.puts " ***Daemon failure #{Time.now} err=#{err} " }
raise
end

How to catch all exceptions as soon as they occur by just one rescue statement

I know how to catch the exceptions but what we do is to put "rescue" after a suspicious section of a code. what if you had a lot functions sending a query to mysql through mysql2 gem and you want to catch their exceptions. One thing you can do is to put a "rescue" statement in each of them. but i want to do that just by one rescue statement. So I put a "rescue" in end of code and put all of code in a "begin" and "end" but it didn't work.
Here is my code and as you see there is a problem in mysql query and just because of "rescue" being end of file, it doesn't catch the exception but when I put it after that query it works.
require 'mysql2'
require 'colored'
begin
def log(string)
p "["+string.cyan+"]"
end
def err
p "["+"FAIL".red+"]"
end
def done
p "["+"DONE".red+"]"
end
class SqlClient
def initialize()
log "SqlClient/initialize"
puts "Host: \n"
#host = gets.strip
puts "User: \n"
#user = gets.strip
puts "Pass: \n"
#pass = gets.strip
#client = Mysql2::Client.new(host: #host , username: #user , password: #pass)
end
def list_databases()
puts "We are listing your databases(not just projects) \n \n \n "
#client.query("ELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA").each do |row|
p row["SCHEMA_NAME"]
end
puts "\n \n \n"
end
end
rescue Mysql2::Error
err
abort
end
`query': You have an error in your SQL syntax; check the manual that corresponds to your
MySQL server version for the right syntax to use near 'ELECT SCHEMA_NAME FROM
INFORMATION_SCHEMA.SCHEMATA' at line 1 (Mysql2::Error)
I'm not looking for something like:
begin
# my code
rescue # this line is right after the code which is going to have problem and we catch it.
end
I'm looking for something like this:
begin
# first method
# second method
# thrid method
# rest of code and etc ...
# now this is end of file:
rescue
end
but as you saw in my code, it didn't work.
UPDATE: I found a similar question here and it seems there will be no answer :| maybe this is a sort of ruby Weakness.
if you want to see ANY error just use e for example
begin
# your call to a method of Mysql2 gem. for example:
client = Mysql2::Client.new(:host => "localhost", :username => "root", etc...)
rescue => e
puts e.message
puts e.backtrace.inspect
end
In order to catch every exception you'd need to wrap each method call with a begin rescue end. When an exception is raised it bails out of the execution so it wouldn't hit the next methods.
To catch all errors I guess I'd do something like this. Keep in mind, this is ugly and I'd recommend for you NOT to do this, but... if you want to try, maybe try something like this:
all_errors = []
# first method you call
begin
# some error might happen here
first_response = Mysql2::Client.new(:host => "localhost", :username => "root", etc...)
rescue => e
all_errors << e
end
# second method you call
begin
# some error might happen here
second_response = Mysql2::Client.new(:host => "localhost", :username => "root", etc...)
rescue => e
all_errors << e
end
puts all_errors.inspect
After a quick search I've found: (http://coderrr.wordpress.com/2008/11/07/the-simple-way-to-print-exceptions-in-ruby/)
# catch all exceptions (anything that derives from Exception)
begin
...
rescue Exception
puts $!, $#
end
You could use an at_exit handler, which has access to the last exception in $!
like
at_exit {
puts "the exception that killed us is", $!
}
If you want to catch Exceptions "as soon as they occur" (not after they're caught) you could use ruby's "debug mode" (which outputs messages when they occur to the console) or ruby-debug see Is there any way to start the Ruby debugger on exception?
Just wrap all your code in:
begin
#yourcode
#as much as you want
rescue
end
Nobody seemed to notice it but using rescue without a class will catch all StandardError and there are so much more.
If you want to catch ALL exceptions you need to do
begin
# your code where you call SqlClient.new etc
rescue Exception => e
puts "error raised"
puts [e, e.backtrace].flatten.join("\n")
end
List of all error classes:
Exception
NoMemoryError
ScriptError
LoadError
NotImplementedError
SyntaxError
SignalException
Interrupt
StandardError
ArgumentError
IOError
EOFError
IndexError
LocalJumpError
NameError
NoMethodError
RangeError
FloatDomainError
RegexpError
RuntimeError
SecurityError
SystemCallError
SystemStackError
ThreadError
TypeError
ZeroDivisionError
SystemExit
fatal
have you tried adding an at_exit method in your class? This would allow you to do something when ruby is exiting. like in this article.
Ruby at_exit
or
From Ruby 2.0 API Docs
However beware of cleverly rescuing from an exception!
You'll start pulling your hair out down the road (or another dev will) when you try to figure out why your code isn't failing when it should be failing. I prefer to fail massively with a bright shiny sign saying the code failed here! hehe.
Good luck!

Resources