I haven't found a good way to test ApplicationRecord methods.
Let's say I have a simple method named one
:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def one
1
end
end
And I want to test it:
describe ApplicationRecord do
let(:it) { described_class.new }
it 'works' do
expect(it.one).to eq 1
end
end
This dies, unsurprisingly, with NotImplementedError: ApplicationRecord is an abstract class and cannot be instantiated.
So I tried the anonymous class suggestion in Testing abstract classes in Rspec:
let(:it) { Class.new(described_class).new }
And this dies with TypeError: no implicit conversion of nil into String
, presumably because the record's table name is nil.
Can anyone suggest a nice, simple way to test ApplicationRecord methods? Hopefully one that doesn't introduce dependencies on other classes in my application and doesn't root around in ActiveRecord internals?
This has been working for me in our tests:
class TestClass < ApplicationRecord
def self.load_schema!
@columns_hash = {}
end
end
describe ApplicationRecord do
let(:record) { TestClass.new }
describe "#saved_new_record?" do
subject { record.saved_new_record? }
before { allow(record).to receive(:saved_change_to_id?).and_return(id_changed) }
context "saved_change_to_id? = true" do
let(:id_changed) { true }
it { is_expected.to be true }
end
context "saved_change_to_id? = false" do
let(:id_changed) { false }
it { is_expected.to be false }
end
end
end
It just prevents the class from attempting a database connection to load the table schema.
Obviously as Rails moves along you might have to update the way you do this but at least it is located in one easy to find place.
I prefer this much more than having another module just to allow testing.