I am writing a spec for a Ruby class that converts a given ActiveRecord into JSON and passes the JSON to another class.
include KinesisHelper
class OrderProcesser
class << self
def post_order(order)
json = extract_order_params(order)
KinesisHelper.send_record_to_kinesis(json, order.stream)
end
private
def extract_order_params(order)
params = {}
params[:id] = order.id
params[:max_budget] = order.budget
params[:startDate] = order.start_date.to_i * 1000
params[:endDate] = order.end_date.to_i * 1000
params.to_json
end
In the RSpec I want to verify if the subject class creates the JSON in the right format and calls its component class with the right arguments. Here is my attempt.
require 'spec_helper'
describe OrderProcesser do
describe "#perform" do
before do
@order = FactoryBot.create(:order)
end
it "should invoke OrderProcesser" do
# working
#KinesisHelper.should_receive(:send_record_to_kinesis).once.with(anything, @order.stream)
#partially working - only first condition is verified
expect(KinesisHelper).to receive(:send_record_to_kinesis) {
|arg1, arg2|
expect(arg2).to eq @order.stream
expect(arg1[:id]).to eq @order.id
}
#when
OrderProcesser.post_order(@order)
end
end
end
The generic verification is passing:
KinesisHelper.should_receive(:send_record_to_kinesis).once.with(anything, @order.stream)
However when I try to verify multiple conditions on the arguments, like the JSON contents and second argument's value, it just checks the first condition. The second condition is ignored.
expect(KinesisHelper).to receive(:send_record_to_kinesis) {
|arg1, arg2|
expect(arg2).to eq @order.stream
expect(arg1[:id]).to eq @order.id #ignored
}
Can you please me know how I can run multiple matchers on the arguments?
The issue is not related to the multiple matches. The error in my code was that I did not parse the JSON string argument to JSON. I also used the symbol values while accessing the JSON attributes. These symbols will eb converted to literal strings after the JSON conversion.
This code snippet works:
expect(KinesisHelper).to receive(:send_record_to_kinesis) {
|arg1, arg2|
expect(arg2).to eq @order.stream
json = JSON.parse(arg1)
expect(json['id']).to eq @order.id
}