gpt4 book ai didi

ruby-on-rails - 在服务测试中剔除 ActiveRecord 模型

转载 作者:数据小太阳 更新时间:2023-10-29 07:39:33 26 4
gpt4 key购买 nike

我正在按照 TDD 方法构建我们的应用程序,并创建一大堆服务对象,严格保持模型用于数据管理。

我构建的许多服务都与模型接口(interface)。以 MakePrintsForRunner 为例:

class MakePrintsForRunner

def initialize(runner)
@runner = runner
end

def from_run_report(run_report)
run_report.photos.each do |photo|
Print.create(photo: photo, subject: @runner)
end
end

end

我很欣赏 create 方法可以抽象到 Print 模型中,但让我们暂时保持原样。

现在,在 MakePrintsForRunner 的规范中,我希望避免包含 spec_helper,因为我希望我的服务规范 super 快。

相反,我像这样删除 Print 类:

describe RunnerPhotos do

let(:runner) { double }
let(:photo_1) { double(id: 1) }
let(:photo_2) { double(id: 2) }
let(:run_report) { double(photos: [photo_1, photo_2]) }

before(:each) do
@service = RunnerPhotos.new(runner)
end

describe "#create_print_from_run_report(run_report)" do

before(:each) do
class Print; end
allow(Print).to receive(:create)
@service.create_print_from_run_report(run_report)
end

it "creates a print for every run report photo associating it with the runners" do
expect(Print).to have_received(:create).with(photo: photo_1, subject: runner)
expect(Print).to have_received(:create).with(photo: photo_2, subject: runner)
end
end

end

一切都变绿了。完美!

...没那么快。当我运行整个测试套件时,根据种子顺序,我现在遇到了问题。

看起来 类 Print; end 行有时会覆盖 print.rb 的 Print 定义(这显然是从 ActiveRecord 继承的),因此在套件中的不同点无法通过一系列测试。一个例子是:

NoMethodError:
undefined method 'reflect_on_association' for Print:Class

这导致了一个不愉快的套房。

关于如何解决这个问题的任何建议。虽然这是一个示例,但有很多次服务直接引用模型的方法,我已经采用上述方法将它们 stub 。有没有更好的办法?

最佳答案

您不必创建 Print 类,只需使用已加载的类并将其 stub 即可:

describe RunnerPhotos do

let(:runner) { double }
let(:photo_1) { double(id: 1) }
let(:photo_2) { double(id: 2) }
let(:run_report) { double(photos: [photo_1, photo_2]) }

before(:each) do
@service = RunnerPhotos.new(runner)
end

describe "#create_print_from_run_report(run_report)" do

before(:each) do
allow(Print).to receive(:create)
@service.create_print_from_run_report(run_report)
end

it "creates a print for every run report photo associating it with the runners" do
expect(Print).to have_received(:create).with(photo: photo_1, subject: runner)
expect(Print).to have_received(:create).with(photo: photo_2, subject: runner)
end
end

end

编辑

如果你真的需要单独在这个测试范围内创建类,你可以在测试结束时取消定义它(来自 How to undefine class in Ruby? ):

before(:all) do
unless Object.constants.include?(:Print)
class TempPrint; end
Print = TempPrint
end
end

after(:all) do
if Object.constants.include?(:TempPrint)
Object.send(:remove_const, :Print)
end
end

关于ruby-on-rails - 在服务测试中剔除 ActiveRecord 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21702305/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com