Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best Practices for RSpec expect raise_error

I have some code for RSpec. My (or not my) Class can (or not) call specific exception. Ex, Class::Foo::Bar::TimeOutError. I want check it.

describe :describe_description do
  before :all do
    object = Class.new
    # method can be call Class::Foo::Bar::TimeOutError
    object.method
  end
  it :exception do
    expect {}.to_not raise_error Class::Foo::Bar::TimeOutError
  end
end

This code worked, but RSpec write a Warning:

WARNING: Using expect { }.not_to raise_error(SpecificErrorClass) risks false positives, since literally any other error would cause the expectation to pass, including those raised by Ruby (e.g. NoMethodError, NameError and ArgumentError), meaning the code you are intending to test may not even get reached. Instead consider using expect {}.not_to raise_error or expect { }.to raise_error(DifferentSpecificErrorClass). This message can be suppressed by setting: RSpec::Expectations.configuration.on_potential_false_positives = :nothing.

How can I fix my code so that the RSpec works correctly and does not issue warnings?

like image 976
Sergey Blohin Avatar asked Sep 17 '25 16:09

Sergey Blohin


2 Answers

No, there isn't a way to apply expect {}.to_not raise_error in the spec without this warning (that's the whole point of adding this warning).

It doesn't make sense logically because you don't need to explicitly check a type of error is not raised.

Scenario 1. The code executes successfully (i.e no errors at all). Then a passing test itself implies there's no Class::Foo::Bar::TimeOutError thrown.

Scenario 2. Another type of error is thrown. Then expect {}.to_not raise_error Class::Foo::Bar::TimeOutError isn't testing anything, it still just passes which creates false positive.

Scenario 3. If you really want to use it, suppress with the setting on_potential_false_positives then the test will continue without the warning. If it passes, then this has no difference with the scenario which makes expect {}.to_not raise_error redundant anyway.

like image 132
Yi Zeng Avatar answered Sep 20 '25 05:09

Yi Zeng


For a future-proof solution I recommend setting

RSpec::Expectations.configuration.on_potential_false_positives = :raise

And fixing any offending examples from

expect { some_call }.to not_raise_error(SomeErrorClass)

to

expect { some_call }.to not_raise_error
# OR
expect { some_call }.to raise_error(SomeOtherErrorClass)
like image 30
Epigene Avatar answered Sep 20 '25 07:09

Epigene