我有一种方法可以创建一对密钥值的交付成本,关键是类型,价值是成本。
def calculate_scoped_job_delivery_costs
delivery_hash = {}
['install', 'fuel', 'breakdown'].each do |scope|
delivery_hash[scope.humanize] = job_delivery_costs.send(scope).inject(0) { |total, item| total + (item.cost_per_unit * item.hour_count) * item.quantity }
end
delivery_hash.delete_if {|key, value| value <= 0 }
end
密钥是作业交付成本模型中的作用域,它会检索该作用域的所有相关成本并将其相加。它有效,但我想测试它的行为,虽然是回顾性的。
所以它的核心预期行为是:
所以我写了这个测试(工厂发布在下面)
let(:jdc1){FactoryGirl.create :job_delivery_cost, job: job, delivery_cost: delivery_cost}
let(:jdc2){FactoryGirl.create :job_delivery_cost, job: job, delivery_cost: delivery_cost}
let(:jdc3){FactoryGirl.create :job_delivery_cost, job: job, delivery_cost: delivery_cost}
describe "calculate_scoped_job_delivery_costs" do
before do
allow(jdc1).to receive(:timing).and_return('fuel')
jdc2.update_attributes(quantity: 4)
jdc2.delivery_cost.update_attributes(timing: 'breakdown')
allow(job).to receive(:job_delivery_costs).and_return(JobDeliveryCost.where(id: [jdc1,jdc2,jdc3].map{|jdc| jdc.id}))
end
it "should retrieve a hash with jdc scopes" do
expect(job.calculate_scoped_job_delivery_costs.is_a?(Hash)).to be_truthy
end
it "should calculate each hash value" do
expect(job.calculate_scoped_job_delivery_costs).to eq "Fuel"=>15.0
end
it "should remove blank values from hash" do
expect(job.calculate_scoped_job_delivery_costs).to_not include "Breakdown"=>0
end
end
所以在上一次测试中,它通过了,为什么?我故意试图通过更新jdc2
上的前一个块中的属性来使其中断,以便breakdown
是另一个范围值。
其次,通过改变jdc2
及其值的状态,这应该打破测试2,因为不再根据相同的值计算燃料。
Here are my factories...
FactoryGirl.define do
factory :job_delivery_cost do
job
delivery_cost
cost_per_unit 1.5
quantity 3
hour_count 1.0
end
end
FactoryGirl.define do
factory :delivery_cost do
title
timing "Fuel"
cost_per_unit 1.5
end
end
FactoryGirl.define do
factory :job do
job_type
initial_contact_id_placeholder {FactoryGirl.create(:contact).id}
title "random Title"
start "2013-10-04 11:21:24"
finish "2013-10-05 11:21:24"
delivery "2013-10-04 11:21:24"
collection "2013-10-05 11:21:24"
delivery_required false
collection_required false
client { Client.first || FactoryGirl.create(:client) }
workflow_state "offer"
admin
end
end
job has_many:job_delivery_costs。 job_delivery_cost belongs_to:delivery_cost has_many:job_delivery_costs has_many:jobs,through :: job_delivery_costs
我真的在努力克服这些测试的逻辑,我确信有比我上面列出的更多的漏洞。我欢迎这方面的批评。
谢谢
答案 0 :(得分:0)
一些建议:
请记住,let
是懒惰评估的;在代码中遇到let
定义的符号之前,不会创建块内的工厂。这可能会对范围之类的事情产生意外后果,您可能认为数据库已包含工厂生成的行。您可以使用let!
(可立即评估)或重组规范以确保按正确顺序创建内容来解决此问题。
我宁愿不去做可以避免的部分存根。对于范围,您可能最好使用工厂,只是让范围检索行而不是存根关系。在您的情况下,这意味着摆脱before
块中的代码并使用工厂设置每个示例,以便范围检索预期值。