rspec check 'with' argument is true - ruby

I have the following rspec example:
describe "with spike" do
it "succeeds" do
a = double('whatever')
a.should_receive(:b).with(true)
a.b('not false')
end
end
How can I make with accept any non-false argument?

Just write an arbitrary message handler:
describe "with spike" do
it "succeeds" do
a = double('whatever')
a.should_receive(:b) { |x|
x.should_not be_false
}
a.b('not false')
end
end

Related

Simplifying `if then` blocks

I have several instances of code that look like this:
if checkProperties(top_properties, payload) == false
return false
end
checkProperties has only one return for false depending on some condition:
def checkProperties(properties, to_check)
properties.each do |property|
if to_check[property.to_s].nil? or to_check[property.to_s].blank?
log_err("Something went wrong")
return false
end
end
end
However I feel this can be simplified. Is it valid to just use the following?
return false unless checkProperties(top_properties, payload)
Any other suggestions?
Don’t return from blocks in the first place. Use break instead:
def checkProperties(properties, to_check)
properties.each_with_object(true) do |property, _|
if to_check[property.to_s].to_s.empty?
log_err("Something went wrong")
break false
end
end
end
or use any? and/or all?:
def checkProperties(properties, to_check)
(!properties.any? { |p| to_check[p.to_s].to_s.empty? }).tap do |good|
log_err("Something went wrong") unless good
end
end
To explicitly show what property was missing, use Enumerable#find:
def empty_property?(properties, to_check)
!!(properties.find { |p| to_check[p.to_s].to_s.empty? }.tap do |prop|
log_err("Property #{prop.inspect} was missing") unless prop.nil?
end)
end
I also took a liberty to renamed a method to follow Ruby naming convention (snake case with a question mark on the end for methods returning true/false.)
Double bang trick is needed to produce true/false out of possible values returned from find: the missing property or nil.
You can check with all? enumerator. This will return true only if all has values below:
def checkProperties(properties, to_check)
properties.all? { |p| to_check[p.to_s] && !to_check[p.to_s].blank? }
end
If any of the property in to_check is nil/absent, all? will return false and stop iterating from there.
Any other suggestions?
A custom error class would work:
class PropertyError < StandardError
end
You could raise it when encountering a missing property:
def check_properties(properties, to_check)
properties.each do |property|
raise PropertyError if to_check[property.to_s].blank?
end
end
This would eliminate the need for conditionals and explicit returns, you'd just have to call:
def foo
check_properties(top_properties, payload)
# do something with top_properties / payload
end
And somewhere "above" you could handle the logging:
begin
foo
rescue PropertyError
log_err 'Something went wrong'
end
Of course, you can also store the missing property's name or other information in the exception to provide a more meaningful error / log message.

rspec vote validations error: must pass hash as an argument

I am trying to write a spec code for a vote_spec model. Not sure what exactly it is I'm doing wrong. I think it may be in the first #vote attribute in the before block.
This is how the validations should work:
Console
v = Vote.new(value: 1)
v.valid? #=> true
v2 = Vote.new(value: -1)
v2.valid? #=> true
v3 = Vote.new(value: 2)
v3.valid? #=> false
This is the error:
Failure/Error: #vote = Vote.create(:post_id)
ArgumentError:
When assigning attributes, you must pass a hash as an argument.
This is my vote_spec.rb
require 'rails_helper'
describe Vote do
describe "validations" do
before do
#vote = Vote.create(:post_id)
#vote.create(value: 1)
#vote.create(value: -1)
end
describe "first_validation" do
it "only allows -1 as a value" do
expect(#vote.first_validation).to eq(-1)
end
end
describe "second_validation" do
it "only allows 1 as a value" do
expect(#vote.second_validation).to eq(1)
end
end
end
end
If you want to test validation, maybe you could do something like this:
describe "validations" do
it 'is valid if the value is 1' do
expect(Vote.new(value: 1)).to be_valid
end
it 'is valid if the value is -1' do
expect(Vote.new(value: -1)).to be_valid
end
[-3, 0, 4].each do |invalid_value|
it "is not valid if the value is #{invalid_value}" do
expect(Vote.new(value: invalid_value)).not_to be_valid
end
end
end
Amanjot,
Also as Sasha mentioned in the comments. You can just continue with this below code I think
require 'rails_helper'
describe Vote do
describe "validations" do
before do
#first_vote = Vote.create(value: -1) # Vote.new(value: -1) - should try this too
#second_vote= Vote.create(value: 1) # Vote.new(value: 1) - should try this too
end
describe "first_validation" do
it "only allows -1 as a value" do
expect(#first_vote.value).to eq(-1)
end
end
describe "second_validation" do
it "only allows 1 as a value" do
expect(#second_vote.value).to eq(1)
end
end
end
Try out something like this. You would need to use the create action on the Vote model.

Rspec and prevent tests from being run under some circumstances

I use rspec like this:
describe
it 'should check if the xx':
end
How do I prevent some tests in the it end body from being run if some condition is met? For example, if the function is_disabled returns true then the following tests should not run:
it 'should check if the xx1':
end
it 'should check if the xx2':
end
but the following should:
it 'should check if the xx3':
end
it 'should check if the xx4':
end
can you do :
context "if api calls enabled for MC, #app.is_disabled => 'USD' do
it 'should check if the xx3':
end
it 'should check if the xx4':
end
end
Yes, you can use rspec implicit filters. Example:
describe "if the app is enabled", :unless => #app.is_disabled do
it 'should check if the xx3':
end
it 'should check if the xx4':
end
end
describe "if the app is disabled", :if => #app.is_disabled do
it 'should check if the xx1':
end
it 'should check if the xx2':
end
end

Using implicit `subject` with `expect` in RSpec-2.11

With the new expect syntax in rspec-2.11, how is it possible to use the implicit subject? Is there a better way than explicitly referencing subject, like below?
describe User do
it 'is valid' do
expect(subject).to be_valid # <<< can `subject` be implicit?
end
end
If you configure RSpec to disable the should syntax, you can still use the old one-liner syntax, since that doesn't involve should being added to every object:
describe User do
it { should be_valid }
end
We briefly discussed an alternate one-liner syntax, but decided against it since it wasn't needed and we felt like it might add confusion. You can, however, easily add this yourself if you prefer how it reads:
RSpec.configure do |c|
c.alias_example_to :expect_it
end
RSpec::Core::MemoizedHelpers.module_eval do
alias to should
alias to_not should_not
end
With this in place, you could write this as:
describe User do
expect_it { to be_valid }
end
With Rspec 3.0 you can use is_expected as described here.
describe Array do
describe "when first created" do
# Rather than:
# it "should be empty" do
# subject.should be_empty
# end
it { should be_empty }
# or
it { is_expected.to be_empty }
end
end
One could use the new named subject syntax, although it's not implicit.
describe User do
subject(:author) { User.new }
it 'is valid' do
expect(author).to be_valid
end
end

Simple Rspec test fails - for what reason?

Coding one of my first rspec tests. headers == nil prints true, but the next test line headers should be_nil fails. Why?
require 'net/http'
$url_arr = []
$url_arr << ...
$url_arr << ...
$url_arr << ...
module NetHelpers
def get_headers(uri)
Net::HTTP.get_response(URI.parse(uri)).get_fields('Set-Cookie')
end
end
describe "new script" do
include NetHelpers
$url_arr.each do |uri|
it "should not return cookies" do
headers = get_headers(uri)
p "==========> #{headers == nil}"
headers should be_nil
end
end
end
Also, the output is
got: "new script" (using ==)
Why "new script" is printed, while headers really contains nil?
Try
headers.should be_nil
instead.

Resources