Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stub i18n_scope for mocking ActiveRecord::RecordInvalid on Rails 4 rspec 3.3.0?

I have tried this code but it raises the error: NameError: uninitialized constant RSpec::Mocks::Mock

RSpec::Mocks::Mock.stub(:i18n_scope).and_return(:activerecord)
model = double(:model, errors: double(:errors, full_messages: []))
ActiveRecord::RecordInvalid.new(model)

How can I stub i18n_scope?

like image 712
Dang Nguyen Avatar asked Dec 07 '25 02:12

Dang Nguyen


1 Answers

To answer your question, you have to stub RSpec::Mocks::Double because that's the class of the instance you're actually passing to ActiveRecord::RecordInvalid. However, that won't work because RSpec::Mocks::Double doesn't implement .i18n_scope. So, what I did (and I hate it) was monkey-patch the RSpec::Mocks::Double class with a dummy method.

  it "does something cool" do
    foo = MyClass.new
    class RSpec::Mocks::Double
      def self.i18n_scope
        :activerecord
      end
    end
    error_double = double(:model, errors: double(:errors,full_messages: ["blah"]))
    expect(foo).to receive(:bar).and_raise(ActiveRecord::RecordInvalid, error_double)
    ...
  end

But there's a better way of doing this by taking advantage of a block argument:

  it "does something cool" do
    foo = MyClass.new
    expect(foo).to receive(:bar) do |instance|
      instance.errors.add(:base, "invalid error")
      raise(ActiveRecord::RecordInvalid, instance)
    end
    ...
  end

This way, you're testing much closer to your application data / logic vs. hacking RSpec.

This worked perfectly for a controller test where I was rescuing from a specific error that was thrown from an #update! method in certain situations.

like image 66
daino3 Avatar answered Dec 08 '25 15:12

daino3



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!