测试将输出范围限定为哈希的方法的行为

时间:2014-08-19 16:28:13

标签: ruby-on-rails ruby rspec

我有一种方法可以创建一对密钥值的交付成本,关键是类型,价值是成本。

  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

密钥是作业交付成本模型中的作用域,它会检索该作用域的所有相关成本并将其相加。它有效,但我想测试它的行为,虽然是回顾性的。

所以它的核心预期行为是:

  1. 它应该输出一个哈希
  2. 应该计算每个范围值
  3. 它应该从哈希
  4. 中删除空白值

    所以我写了这个测试(工厂发布在下面)

    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

    我真的在努力克服这些测试的逻辑,我确信有比我上面列出的更多的漏洞。我欢迎这方面的批评。

    谢谢

1 个答案:

答案 0 :(得分:0)

一些建议:

请记住,let是懒惰评估的;在代码中遇到let定义的符号之前,不会创建块内的工厂。这可能会对范围之类的事情产生意外后果,您可能认为数据库已包含工厂生成的行。您可以使用let!(可立即评估)或重组规范以确保按正确顺序创建内容来解决此问题。

我宁愿不去做可以避免的部分存根。对于范围,您可能最好使用工厂,只是让范围检索行而不是存根关系。在您的情况下,这意味着摆脱before块中的代码并使用工厂设置每个示例,以便范围检​​索预期值。