【问题标题】:RSpec: Testing out models with methods that call update_attributesRSpec:使用调用 update_attributes 的方法测试模型
【发布时间】:2012-01-21 16:33:12
【问题描述】:

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

结束

实践.rb

def marking_completed       

# Update user points
user.add_points(100)
self.completed = true
self.save!

结束

在 User.rb 中

def add_points(points)
self.points += points
update_attributes(:points => self.points)

结束

【问题讨论】:

  • 您有任何可以发布的代码和测试示例吗?
  • 我已经更新了代码,请看一下!谢谢

标签: ruby-on-rails-3.1 rspec2 rspec-rails


【解决方案1】:

发生的情况是用户对象缓存在@practice 变量上,因此需要在用户更新时重新加载。对于当前的规范,您对此无能为力,但您可能想考虑一下您实际测试的是什么。在我看来,您的规范是针对练习模型的,但断言 should change { @practice.user.points }.by(20) 确实在描述用户行为,这对我来说似乎很奇怪。

我个人会在您的规范中将实践模型和用户模型进一步解耦,并独立测试它们的行为。

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

然后我会为 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

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

【讨论】:

  • 感谢您非常全面的解释。欣赏!
  • 没有问题,这让我措手不及的次数超出了我的记忆。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多