2016-02-12 43 views
2

我还没有找到测试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.

所以我尝试了匿名上课建议Testing abstract classes in Rspec

let(:it) { Class.new(described_class).new } 

而这种死亡与TypeError: no implicit conversion of nil into String,大概是因为记录的表名是零。

任何人都可以提出一个好的,简单的方法来测试ApplicationRecord方法?希望有一个不会在我的应用程序中引入对其他类的依赖关系,并且不会在ActiveRecord内部驻留?

回答

5

我建议提取这些方法为模块(关注),并独自离开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 
+0

是的!就个人而言,我避免担忧(我认为这有很好的辩论)。但是,我同意远离ActiveRecord上的'abstract_class'。 – jvillian

+1

为单行函数创建关注文件?这感觉就像是扭曲我的应用程序的源代码以弥补语言/库的限制。我仍然希望有人可以建议如何测试ApplicationRecord类本身,但是非常感谢你写出了很好的建议! – bronson

0

这已经为我工作在我们的测试:

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 

它只是防止类试图从数据库连接加载表模式。

显然,随着Rails的移动,你可能不得不更新你这样做的方式,但至少它位于一个容易找到的地方。

我比另一个模块更容易测试。