我有一个Rails引擎,其中包含链接到某些主机应用程序类的方法(我知道这种类型的耦合很糟糕,但在这种情况下它是不可避免的)。
我需要测试使用主机类的方法,但在尝试加倍/模拟/存根主机的类时uninitialized constant MyEngine::BaseUser
或BaseUser
或在这种情况下Tutor
。)
我已经通过创建模拟类来解决这个问题,但我认为我所留下的是一个坏主意并且意味着我的测试不太有用(见下文)。
知道我可以做得更好,还是建议更好的方向进入?
正如我上面所说,我(这很糟糕)就这样:
BaseUser = Class.new do
attr_accessor :id
def initialize(id = 1)
@id = id
end
def self.find(id)
self.new(id)
end
def tutor
Tutor.find(self.id)
end
end
class Tutor
attr_accessor :id, :first_name
def initialize(id = 1)
@id = id
@first_name = "Tutor with ID #{id}'s first name"
end
def self.find(id)
self.new(id)
end
end
it 'returns the hosts first name' do
allow(MyEngine).to receive_message_chain(:user_class, :constantize) { BaseUser }
ai = FactoryGirl.create(:availability_interval, host_id: 1)
expect(ai.host_first_name).to eq BaseUser.find(1).tutor.first_name
end
我正在测试的方法如下:
def host_full_name
MyEngine.user_class.constantize.find(self.host_id).tutor.full_name
end
(MyEngine.user_class
是" BaseUser")
答案 0 :(得分:1)
您的引擎将所有内容命名为引擎。如果您正在尝试访问实际在基本作用域中定义的类(即在引擎之外),则可以强制它使用::
在基本作用域中查找该类,例如:
expect(ai.host_first_name).to eq ::BaseUser.find(1).tutor.first_name
答案 1 :(得分:0)
我在问题中所做的似乎仍然是最好的解决方案,所以我继续用这种方法的另一个例子来回答这个问题。
在这里,我需要模拟/模拟代码中使用的Setting
{引擎外} my_value = Setting.find_by_name('SETTING_NAME').value
describe 'ratable_based_on_time' do
Setting = Class.new do
def self.value
end
def self.find_by_name(name)
end
end
before(:each) do
allow(Setting).to receive_message_chain(:find_by_name, :value).and_return("30")
end
let(:availability_interval) { FactoryGirl.create(:availability_interval) }
it 'should return availability_intervals that are rateable based on time since start' do
availability_interval.update_column(:start_time, 1.hour.ago)
availability_interval.reload
expect(AvailabilityInterval.ratable_based_on_time).to eq [availability_interval]
end
it 'should not return availability_intervals that are not rateable based on time since start' do
availability_interval.update_column(:start_time, 25.minutes.ago)
availability_interval.reload
expect(AvailabilityInterval.ratable_based_on_time).to eq []
end
end