I'm mocking active record invalid exception in the rspec.
here is the method im facing problem with. image_processing_error checks for the errors of the image object.
def save_image(image)
begin
image.save!
{ message: I18n.t("messages.image_saved") , status: 200 }
rescue ActiveRecord::RecordInvalid
image_processing_error(image)
end
end
private
def image_processing_error(image = nil)
if image && image.errors.any? && image.errors.messages.any?
{ message: image.errors.messages.values[0][0] , status: 422 }
else
{ message: I18n.t("errors.invalid_request"), status: 422 }
end
end
And here is my rspec for the same
# frozen_string_literal: true
require "rails_helper"
RSpec.describe ImagesService do
describe ".save_image" do
context "save image throws error" do
let(:image) { double("image", { "errors": { "messages": { "name": ["is invalid", "must be implemented"]}}}) }
before do
allow(image).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
end
subject { described_class.save_image(image) }
it "raised the error" do
// I want to test the **ActiveRecord::RecordInvalid
// I places NoMethodError to just pass the test
expect { subject }.to raise_error NoMethodError
expect { subject }.to raise_error ActiveRecord::RecordInvalid
end
end
end
end
I'm getting below error when i read the image error. what is the proper double value i have to keep it to work.
Failures:
1) ImagesService.save_image save image throws error raised the error
Failure/Error: expect { subject }.to raise_error ActiveRecord::RecordInvalid
expected ActiveRecord::RecordInvalid, got #<NoMethodError: undefined method `messages' for {:messages=>{:name=>["is invalid", "must be implemented"]}}:Hash> with backtrace:
In this case, the reason why you are not getting an exception on the call to subject
is because an exception is not raised by it. Since you have set a rescue block in the save_image
, if an exception is thrown inside of it, the rescue block will be called and the exception is not going to be propagated to the caller instead image_processing_error
is going to be called.
So in your spec, when you call subject
you are not going to get an exception but instead, you are going to get the parsed errors from image_processing_error
which as I understand is actually the expected behavior.
In this case, what you could do is to test that the result you are getting from subject
match with the expected error message that you would get in this case, something like:
it "returns the error messages" do
expect(response.body).to include("is invalid", "must be implemented")
end