如何测试 ApplicationRecord 抽象基 class 中的方法?
How can I test methods in the ApplicationRecord abstract base class?
我还没有找到测试 ApplicationRecord 方法的好方法。
假设我有一个名为 one
:
的简单方法
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def one
1
end
end
我想测试一下:
describe ApplicationRecord do
let(:it) { described_class.new }
it 'works' do
expect(it.one).to eq 1
end
end
不出所料,NotImplementedError: ApplicationRecord is an abstract class and cannot be instantiated.
所以我尝试了 中的匿名 class 建议:
let(:it) { Class.new(described_class).new }
这与 TypeError: no implicit conversion of nil into String
一起消失,大概是因为记录的 table 名称为 nil。
任何人都可以建议一种测试 ApplicationRecord 方法的简单好方法吗?希望它不会在我的应用程序中引入对其他 class 的依赖性并且不会在 ActiveRecord 内部产生影响?
我建议将这些方法提取到模块(关注)中,并单独保留 ApplicationRecord。
module SomeCommonModelMethods
extend ActiveSupport::Concern
def one
1
end
end
class ApplicationRecord < ActiveRecord::Base
include SomeCommonModelMethods
self.abstract_class = true
end
describe SomeCommonModelMethods do
let(:it) { Class.new { include SomeCommonModelMethods }.new } }
it 'works' do
expect(it.one).to eq 1
end
end
这在我们的测试中对我有用:
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
它只是阻止 class 尝试通过数据库连接加载 table 模式。
显然,随着 Rails 的发展,您可能需要更新执行此操作的方式,但至少它位于一个容易找到的地方。
我更喜欢这个,而不是仅仅为了测试而使用另一个模块。
如果您正在使用 Rspec,那么您可以创建一个 shared example,然后从继承自 ApplicationRecord 的每个模型的规范中调用它。这将有在每个模型上测试所有这些行为的缺点,但除非您将大量共享行为塞进 ApplicationRecord 中,否则开销应该相当低。
我还没有找到测试 ApplicationRecord 方法的好方法。
假设我有一个名为 one
:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def one
1
end
end
我想测试一下:
describe ApplicationRecord do
let(:it) { described_class.new }
it 'works' do
expect(it.one).to eq 1
end
end
不出所料,NotImplementedError: ApplicationRecord is an abstract class and cannot be instantiated.
所以我尝试了
let(:it) { Class.new(described_class).new }
这与 TypeError: no implicit conversion of nil into String
一起消失,大概是因为记录的 table 名称为 nil。
任何人都可以建议一种测试 ApplicationRecord 方法的简单好方法吗?希望它不会在我的应用程序中引入对其他 class 的依赖性并且不会在 ActiveRecord 内部产生影响?
我建议将这些方法提取到模块(关注)中,并单独保留 ApplicationRecord。
module SomeCommonModelMethods
extend ActiveSupport::Concern
def one
1
end
end
class ApplicationRecord < ActiveRecord::Base
include SomeCommonModelMethods
self.abstract_class = true
end
describe SomeCommonModelMethods do
let(:it) { Class.new { include SomeCommonModelMethods }.new } }
it 'works' do
expect(it.one).to eq 1
end
end
这在我们的测试中对我有用:
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
它只是阻止 class 尝试通过数据库连接加载 table 模式。
显然,随着 Rails 的发展,您可能需要更新执行此操作的方式,但至少它位于一个容易找到的地方。
我更喜欢这个,而不是仅仅为了测试而使用另一个模块。
如果您正在使用 Rspec,那么您可以创建一个 shared example,然后从继承自 ApplicationRecord 的每个模型的规范中调用它。这将有在每个模型上测试所有这些行为的缺点,但除非您将大量共享行为塞进 ApplicationRecord 中,否则开销应该相当低。