【问题标题】:Rspec Test validations of 'on: : update' not working (Rails4/Rspec 3)'on::update' 的 Rspec 测试验证不起作用(Rails4/Rspec 3)
【发布时间】:2015-09-21 06:26:28
【问题描述】:

我有一个模型,我在其中实现了验证以防止在设置初始值后(在对象创建期间)发生更改。

它是这样工作的:

models/deal.rb

validate :quantity_not_changeable, on: :update

def quantity_not_changeable
      if quantity_changed?
        errors.add(:quantity,
         "Change of the initially defined qty is not possible")
      end
    end

这在我的应用程序中有效:我创建了一个新交易,它有效。我尝试通过更改“数量”字段来编辑它,但它失败了。我尝试编辑另一个字段(“数量”除外),它有效。 所以一切正常。

但我的 Rspec 测试失败了。

其实我知道它不起作用,因为on::validate有问题。

确实没有'on::validate',测试通过了,但我当然不能只删除'on::update',因为我只希望用户在初始创建后不能编辑它交易)。

describe Deal do

  let(:admin_user) { FactoryGirl.create(:admin_user) }

  before(:each) do
    @attr = {
      title:                              "Neque porro quisquam est qui dolorem",
      description:                        "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum",
      quantity:  10
    }
  end

describe "my test" do

 describe "test that nb of quantity can't be changed after initial creation" do    
    it "fails if initial quantity is changed" do 
      deal = Deal.create(@attr)
      deal.update(quantity: 15)     
      expect(deal).to have(1).errors_on(:quantity)

    end
  end

但我收到此 rspec 错误:

Failure/Error: expect(deal).to have(1).errors_on(:quantity)
       expected 1 errors on :quantity, got 0

我将使用下面的“打印变量”:p 交易向您展示为什么我确定它是由于 on::update 在 TESTS 中不起作用。

首先:如果我在更新之前放置“p deal”,让我们看看交易对象的值:

describe "my test" do

 describe "test that nb of quantity can't be changed after initial creation" do    
    it "fails if initial quantity is changed" do 
      deal = Deal.create(@attr)
      p deal
      deal.update(quantity: 15)     
      expect(deal).to have(1).errors_on(:quantity)

    end
  end

我得到以下输出(我们看到一切正常:数量确实是10)

#<title: "Neque porro quisquam est qui dolorem", description: "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lo...", quantity: 10>

第二个:现在让我们在我尝试更新“数量”的值之后移动“p deal”

describe "my test" do

 describe "test that nb of quantity can't be changed after initial creation" do    
    it "fails if initial quantity is changed" do 
      deal = Deal.create(@attr)
      deal.update(quantity: 15)
      p deal     
      expect(deal).to have(1).errors_on(:quantity)

    end
  end

现在的输出是:(我们看到由于代码中的 validate on: :update 与我们预期的相反,不幸的是,Rspec 测试确实设法更新了数量的值) :

#<title: "Neque porro quisquam est qui dolorem", description: "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lo...", quantity: 15>

所以我不明白为什么实际上我手动测试并且无法更新,但是在我的 rspec 测试套件中它确实更新了!!!

几个小时来理解它,但没有成功...我试图找到一些在线资源,有人说on: :update is a weak way to do things。我真的不知道如何处理这个奇怪的错误。

请帮忙。

【问题讨论】:

  • p deal 显示数量已更改,但不显示记录已成功保存。如果您在控制台中执行deal.update(quantity: 15),您将看到记录未保存,但在检查(未保存的)记录时属性已更改。在p deal 之前尝试deal.reload 以确认它是否已更改。 (不过,我不知道为什么你的期望失败了......)
  • 谢谢史蒂夫,我会试试这个。

标签: ruby-on-rails ruby ruby-on-rails-4 rspec


【解决方案1】:

我猜由于其他验证,调用create 方法时没有保存条目。您可以尝试使用rails c 打开控制台并评估以下内容:

deal = Deal.create(title: 'mytitle', description: 'mydescription', quantity: 10)
deal.persisted?

那么如果你得到 false 以找出创建时的错误:

deal.errors.messages

编辑

此测试应该通过:

it "fails if initial quantity is changed" do 
  deal = Deal.create(@attr)
  deal.update(quantity: 26)     
  expect(deal.errors.messages).to eq({quantity: ["Change of the initially defined qty is not possible"]})
end

但这些不应该:

it "exploited test that should not pass because messages hash should not be empty" do 
  deal = Deal.create(@attr)
  deal.update(quantity: 26)     
  expect(deal.errors.messages.empty?).to eq(true)
end

it "exploited test in other variation" do 
  deal = Deal.create(@attr)
  deal.update(quantity: 26)     
  expect(deal.errors.messages).to eq({})
end

【讨论】:

  • 我快疯了....deal.persisted?不会引发错误(它等于 true),因此 deal.errors.message 为空/什么都不出现
  • @Mathieu 奇怪的是,在编辑部分尝试我的测试代码会返回什么?
  • 测试通过!那是什么意思呢?
  • 我终于成功了:放弃@attr 并搬到工厂女孩那里进行测试。让它成功的唯一方法。
  • 稍微修改答案以获得正确的映射。如果您通过控制台运行创建然后更新方法,是否会出现 ROLLBACK?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多