Ruby on rails 分析Mongoid事件生成的ActiveRecord对象时,Rspec测试随机失败
我实现了一个基于Mongoid的活动日志机制,它将事件保存在MongoDB中 Mongoid模型Ruby on rails 分析Mongoid事件生成的ActiveRecord对象时,Rspec测试随机失败,ruby-on-rails,mongodb,activerecord,rspec,Ruby On Rails,Mongodb,Activerecord,Rspec,我实现了一个基于Mongoid的活动日志机制,它将事件保存在MongoDB中 Mongoid模型Activity具有after\u创建事件,根据记录的活动类型执行不同的任务:(简化示例) 测试如下所示: it 'should hide previous [objects] create a new updated one' do 2.times do user.log_activity(:user_did_something) end i
Activity
具有after\u创建事件,根据记录的活动类型执行不同的任务:(简化示例)
测试如下所示:
it 'should hide previous [objects] create a new updated one' do
2.times do
user.log_activity(:user_did_something)
end
items = MyItems.where(:type => :user_did_something)
items.count.should == 2
end
end
let(:items_count) { MyItems.where(:type => :user_did_something).count }
it 'should hide previous [objects] create a new updated one' do
expect { 2.times { user.log_activity(:user_did_something) } }.
to change { items_count }.from(0).to(2)
end
有时,对项的测试失败。计数为0而不是2。
仅当从命令行运行时才会发生这种情况rspec spec
仅运行此测试或使用Guard运行所有测试时,不会发生这种情况。假设问题在于测试设置(而不是代码)中的某些竞争条件,我建议使用rspec,它应该等待在DB中创建对象,然后再对其进行计数:
it 'should hide previous [objects] create a new updated one' do
items = MyItems.where(:type => :user_did_something)
expect { 2.times { user.log_activity(:user_did_something) } }.
to change { items.count }.from(0).to(2)
end
[编辑]
为了使测试总体上更干净(虽然这不会影响行为,但我不认为),您还可以使用rspec的延迟加载let
,如下所示:
it 'should hide previous [objects] create a new updated one' do
2.times do
user.log_activity(:user_did_something)
end
items = MyItems.where(:type => :user_did_something)
items.count.should == 2
end
end
let(:items_count) { MyItems.where(:type => :user_did_something).count }
it 'should hide previous [objects] create a new updated one' do
expect { 2.times { user.log_activity(:user_did_something) } }.
to change { items_count }.from(0).to(2)
end
在典型的Mongodb设置中,数据库写入成功返回和数据读取之间可能存在延迟。原因有两个:
- 为了提高性能,在将数据提交到磁盘之前,可能会返回“不安全”写入李>
- Mongodb使用副本集,存在复制延迟。通常,读取作为负载平衡的一种形式分发到副本,因此即使使用安全写入,也可能是从与刚写入的服务器不同的服务器读取,因此看不到刚写入的数据
为了确保始终能够立即读回刚刚使用Mongoid编写的数据,需要设置数据库会话选项一致性::strong,安全性:true
,这两个选项都不是默认选项 对于单元测试,您的测试涵盖了很多内容:
调用创建
回调后的
在用户做了某件事之后调用
已创建MyItem
对象
我建议您将其分解为几个单元测试,每个单元测试一件事情。你从中得到的附加值是,至少,你会知道测试的哪个部分实际上失败了
class Activity
include Mongoid::Document
after_create { |activity| my_after_create_callback(activity.event_type) }
def my_after_create_callback(activity_type)
method_name = "after_#{activity_type}"
send(method_name) if respond_to? method_name
end
def after_user_did_something
MyItem.create!(:type => :user_did_something)
end
end
您能否提供log\u活动
code?当您说“设置数据库会话选项”时,我们如何在config/mongoid.yml
Rails应用程序中做到这一点?这些密钥需要在config/mongoid.yml
文件的哪个父密钥中设置?