RSpec:使用调用update_attributes的方法测试模型

Ben*_*Hao 4 rspec2 rspec-rails ruby-on-rails-3.1

RSpec新手在这里.

我正在尝试测试我的模型,这些模型具有update_attributes用于更新其他模型的值的方法.

我确信这些值在数据库中持久存在,但它们没有传递规范.

但是,当我包含类似@user.reload它的东西时.

我想知道我是不是做错了.具体来说,如何测试改变其他模型属性的模型?

更新代码:

describe Practice do

before(:each) do
    @user = build(:user)
    @user.stub!(:after_create)
    @user.save!

    company = create(:acme)
    course = build(:acme_company, :company => company)
    course.save!

  @practice = create(:practice, :user_id => @user.id, :topic => "Factors and Multiples" )
end

describe "#marking_completed" do

    it "should calculate the points once the hard practice is done" do
        @practice.question_id = Question.find(:first, conditions: { diff: "2" }).id.to_s
        @practice.responses << Response.create!(:question_id => @practice.question_id, :marked_results => [true,true,true,true])
        @practice.save!

        lambda {
            @practice.marking_completed
            @practice.reload # <-- Must add this, otherwise the code doesn't work
        }.should change { @practice.user.points }.by(20)
    end
end
Run Code Online (Sandbox Code Playgroud)

结束

在Practice.rb

def marking_completed       

# Update user points
user.add_points(100)
self.completed = true
self.save!
Run Code Online (Sandbox Code Playgroud)

结束

在User.rb中

def add_points(points)
self.points += points
update_attributes(:points => self.points)
Run Code Online (Sandbox Code Playgroud)

结束

Pet*_*own 5

发生的事情是用户对象缓存在@practice变量上,因此在用户更新时需要重新加载.使用当前规范,您无法做到这一点,但您可能想要考虑一下您实际测试的内容.对我来说,你的规范是针对Practice模型的,这似乎很奇怪,但断言should change { @practice.user.points }.by(20)实际上是在描述User行为.

我个人会在你的规范中将实践和用户模型分开一些,并独立测试他们的行为.

describe "#marking_completed" do
  before do
    @practice.question_id = Question.find(:first, conditions: { diff: "2" }).id.to_s
    @practice.responses.create!(:question_id => @practice.question_id, :marked_results => [true,true,true,true])
    @practice.save!
  end

  it "should calculate the points once the hard practice is done" do
    @practice.user.should_receive(:add_points).with(20).once
    @practice.marking_completed
  end
end
Run Code Online (Sandbox Code Playgroud)

然后我会为User模型添加一个单独的测试:

describe User do
  it 'should add specified points to a user' do
    lambda { subject.add_points(100) }.should change { subject.points }.by(100)
  end
end
Run Code Online (Sandbox Code Playgroud)

另一种旁注是,不清楚Question.find返回的是什么,或者为什么用户的分数在测试中会改变20.