【发布时间】:2014-08-28 17:29:06
【问题描述】:
让我快速解释一下:
我正在使用 Rspec 测试 rails 4 模型关注点。我做了shared_examples_for Uuidable (Uuidable 是关注名称)
关注点非常简短易懂,所以我在下面粘贴代码:
module Uuidable
extend ActiveSupport::Concern
included do
before_create :generate_uuid
end
protected
def generate_uuid
self.uuid = loop do
uuid = SecureRandom.uuid
break uuid unless uuid_exists?
end
end
private
def uuid_exists?
self.class.exists?(uuid: uuid)
end
end
问题是当我在 RSpec 内部测试时:
let(:model) { FactoryGirl.build(described_class) }
it 'should not generate same uuid' do
SecureRandom.stub(:uuid).and_return("c640f32c-e21b-44ea-913e-7041fdb6de85", "c640f32c-e21b-44ea-913e-7041fdb6de85", "e93f0130-3a81-406f-8871-609d89ae0850")
model.save
expect(FactoryGirl.create(described_class).uuid).not_to eq(model.uuid)
end
现在事情变得非常有趣了:
为什么? Expect 失败。原因?哦,好吧..
所以为了调试它,我在里面添加了binding.pry
def generate_uuid
self.uuid = loop do
uuid = SecureRandom.uuid
binding.pry
break uuid unless uuid_exists?
end
end
让我通过屏幕截图分享控制台输出:
让我快速引导您完成它:
第一个=> 来自model.save。首先调用了SecureRandom.stub(:uuid)。一切都很好,所以我这样做了exit
第二个=> 来自FactoryGirl.create(described_class)。存根 SecureRandom.uuid 应该返回与以前模型中相同的 uuid,并且确实如此 *(调用 [1] 和 [1])。
我现在期望发生的事情:uuid_exists? return true 所以循环重新启动并获得第三个存根 SecureRandom.uuid 然后保存模型。但是在电话[2] uuid_exists? 中,我们得到了...false ?!?!什么?
好的,也许创建最后一个模型时出了点问题,所以我将手动从uuid_exists? 调用代码。
哇哇哇?!它返回true!!!!。不敢相信,所以我在电话[4] 中重新定义了整个方法。它仍然返回false。然后很少进行手动测试以确保最后一个模型是否存在并且具有 uuid。它确实
调用[10] 后测试失败,这意味着它没有再次通过loop。
谁能解释一下这种奇怪的行为?
编辑#1
当我将unless 语句中的uuid_exists? 调用更改为self.class.exists?(uuid: uuid) 时,它通过了。我很困惑
编辑#2
根据要求,我正在从控制台粘贴文本:
19:51:34 - INFO - Running: spec/models/review_spec.rb
*********.
From: /Users/filip/programming/service_matters/app/models/concerns/uuidable.rb @ line 13 Uuidable#generate_uuid:
10: def generate_uuid
11: self.uuid = loop do
12: uuid = SecureRandom.uuid
=> 13: binding.pry
14: break uuid unless uuid_exists?
15: end
16: end
[1] pry(#<Review>)> uuid
=> "c640f32c-e21b-44ea-913e-7041fdb6de85"
[2] pry(#<Review>)> exit
From: /Users/filip/programming/service_matters/app/models/concerns/uuidable.rb @ line 13 Uuidable#generate_uuid:
10: def generate_uuid
11: self.uuid = loop do
12: uuid = SecureRandom.uuid
=> 13: binding.pry
14: break uuid unless uuid_exists?
15: end
16: end
[1] pry(#<Review>)> uuid
=> "c640f32c-e21b-44ea-913e-7041fdb6de85"
[2] pry(#<Review>)> uuid_exists?
=> false
[3] pry(#<Review>)> self.class.exists?(uuid: uuid)
=> true
[4] pry(#<Review>)> def uuid_exists?
[4] pry(#<Review>)* self.class.exists?(uuid: uuid)
[4] pry(#<Review>)* end
=> :uuid_exists?
[5] pry(#<Review>)> uuid_exists?
=> false
[6] pry(#<Review>)> self
=> #<Review id: nil, organization_id: 3, attitude: 1, feedback_action: "Refund", feedback_details: "Normandia SV2 didn't have AI module", approved: false, uuid: nil, feedback_date: "2014-08-18 17:51:58", created_at: "2014-08-28 17:51:58", updated_at: "2014-08-28 17:51:58", category_id: 3>
[7] pry(#<Review>)> self.uuid
=> nil
[8] pry(#<Review>)> Review.count
=> 1
[9] pry(#<Review>)> Review.first.uuid
=> "c640f32c-e21b-44ea-913e-7041fdb6de85"
[10] pry(#<Review>)> exit
F
【问题讨论】:
标签: ruby-on-rails ruby activerecord ruby-on-rails-4 rspec