rspec赋值变量 - 错误:预期:“已完成”得到:“待定”(使用==进行比较)

时间:2015-04-30 19:24:57

标签: ruby-on-rails testing rspec controller factory-bot

我正在使用RSPEC和Factories(使用 工厂女工) 控制器代码:

class JobsController < ApplicationController
  before_action :authenticate_member!
  before_action :set_job

def complete
  @job.status = "completed"
  @job.save!
  Event.where("job_id = ? AND starts_at > ?", @job.id, DateTime.now).destroy_all
  redirect_to scheduler_path
  puts @job.inspect
end

  def set_job
    @job = Job.find(params[:id] || params[:job_id])
  end

end

RSPEC代码:

describe JobsController do
  login_user

  before do 
    @job=FactoryGirl.create(:job)
  end

  describe "Complete Action" do 
    it "sets job status to complete" do 
      puts @job.inspect
      get :complete, :id=>@job.id
      @job.status.should eq("Completed")
    end
  end

错误:

 expected: "Completed" got: "pending" (compared using ==)

注意控制器代码的输出是:

#<Job id: 12, name: nil, status: "completed">

所以我知道它在控制器中发生了变化,但为什么它会在工厂女孩中回到“待定”?注2:待定是默认值。 我误解了控制器和工厂女孩之间的关系吗?

请帮帮忙?!

2 个答案:

答案 0 :(得分:1)

这里发生的事太多了。

首先,当状态设置为Completed并且案例为C时,您不能指望completed使用大写c

其次,有两条puts @job.inspect行 - 一行在控制器中,另一行在测试中;确保你能够区分两者的输出。

最后,在控制器测试中,在get语句之后,您需要@job.reload以确保从数据库更新@job对象。如果没有@job.reload,您仍然会看到@job.status的原始值 - 正确设置为pending(我假设出厂)

有关为何需要@job.reload的更全面解释,请参阅https://stackoverflow.com/a/7449957/429758

完整的控制器测试如下:

describe "Complete Action" do 
  it "sets job status to complete" do 
    @job.status.should eq("pending") # Optionally check the original status
    get :complete, :id=>@job.id
    @job.reload
    @job.status.should eq("completed")
  end
end

答案 1 :(得分:1)

您应该尝试重新加载@job

@job.reload.status.should eq "completed"

请注意,我已将Completed更改为预期字符串中的completed

旁注

除此之外,我注意到您使用了before_action来检索作业,这可以通过不同的方式完成。您也没有检查作业是否已保存,并且始终重定向到scheduler_path。您可能想要更改它。我会亲自做这样的事情:

class JobsController < ApplicationController
  before_action :authenticate_member!

  def complete
    if job.update_attributes status: :completed
      Event.where("job_id = ? AND starts_at > ?", job.id, DateTime.now).destroy_all
      redirect_to scheduler_path
    else
      # do something else, perhaps redirect to scheduler_path with an alert?
    end
  end

  def job
    @job ||= Job.find(params[:id] || params[:job_id])
  end

end