我试图针对两个不同的问题编写两个RSpec测试,这些测试比我以前编写的要先进得多。
我要在控制器中测试的内容:
def index
@buildings ||= building_class.active.where(place: current_place)
end
我尝试编写RSpec测试:
describe 'GET :index' do
it "assigns @buildings" do
@buildings ||= building_class.active.where(place: current_place)
get :index
expect(assigns(:buildings)).to eq([building])
end
end
该测试失败,甚至无法运行,所以我知道我缺少某些东西。
第二个测试需要测试类方法的返回值。这是我需要在控制器中测试的内容:
def class_name
ABC::Accountant::Business
end
这是我测试此方法的尝试:
describe "class name returns ABC::Accountant::Business" do
subject do
expect(subject.class_name).to eq(ABC::Accountant::Business)
end
end
答案 0 :(得分:0)
对于第一次测试,我会做这样的事情:
首先,我将.active.where(place: current_place)
移至范围(我猜building_class
返回Building
或类似的内容)
class Building << ApplicationRecord
scope :active_in, -> (place) { active.where(place: place)
那么对测试进行存根比较容易
describe 'GET :index' do
it "assigns @buildings" do
scoped_buildings = double(:buildings)
expect(Building).to receive(:active_in).and_return(scoped_buildings)
get :index
expect(assigns(:buildings)).to eq(scoped_buildings)
end
end
然后您的控制器将执行
@buildings ||= building_class.active_in(current_place)
这样,您就可以测试两件事:控制器实际上调用了作用域,并且控制器在@buildings
变量上分配了返回的值(您实际上不需要测试实际的对象,您可以测试型号规格上的范围)。
就个人而言,我认为最好使用相同的范围概念来进行@buildings = current_place.active_buildings
之类的测试,以测试您正在获取当前位置的活跃建筑物。
编辑:如果您不能修改控制器,则存根稍有不同,它暗示了一些我不希望显式测试的方法。
scoped_buildings = double(:buildings)
controller.stub_chain(:building_class, :active, :where).and_return(scoped_building)
get :index
expect(assings(:buildings)).to eq scoped_buildings
请注意,现在您的测试依赖于特定的实现,并且测试实现是一种不良习惯,应该测试行为而不是实现。
第二,我猜类似的东西应该起作用:
describe ".class_name" do
it "returns ABC::Accountant::Business" do
expect(controller.class_name).to eq(ABC::Accountant::Business)
end
end
恕我直言,如果方法的名称令人困惑,class_name
会提示它返回一个字符串,而不是返回一个名称,而是返回一个类。也许您可以将该方法更改为resource_class
或不太混乱的东西。