在单元测试中使用created_at进行排序,并在rails中生成数据

时间:2009-11-15 18:16:38

标签: mysql ruby-on-rails ruby unit-testing

我有一些代码基本上显示了给定表中的最后一个x(变量,但是假设x在这里是20)。在其中一个单元测试中,我有这个片段:

EditedItem.push_to_queue(hiddennow)
#create some new entries and save them
20.times{ EditedItem.push_to_queue(random_item) }
Queue.get_entries.each{|entry| assert_not_equal too_far_down, entry}

可能或者可能不是很漂亮,但它有意图。 hiddennow对象已在队列中被推下太远,并且在调用get_entries时不应再返回。

#this works
SearchObject.find(:all, :order => "id desc")

#this does not, unless the 20.times loop has sleep(1) or something
SearchObject.find(:all, :order => "created_at desc")

这简化了一下,但看起来像20次循环添加的东西足够快,以至于created_at上的order by子句无法区分。我的问题是,我做了一些根本错误的事情吗?如果没有,沿着这些方向编写测试的更好方法是什么?

2 个答案:

答案 0 :(得分:5)

DigitalRoss是对的。 created_at具有一秒的粒度。

一个选项是在创建对象时设置created_at

old = EditItem.new(:created_at => 1.second.ago)
older = EditItem.new(:created_at => 2.seconds.ago)

另一种选择是实际使用存根来弄乱Time类。以下内容适用于Rspec,但可以通过其他模拟框架(如Mocha)轻松完成。

@seconds = Time.now.to_i
Time.stub!(:now).and_return{Time.at(@seconds += 5) }

每次拨打Time.now时,此时间将比上一次返回5秒。

如果你能让它发挥作用,我会推荐第一种方法,因为你做得更清楚,不太可能产生意想不到的后果。

答案 1 :(得分:1)

与文件和记录相关的时间(特别是Rails中的那些时间)通常保存在 Unix time , or POSIX time中。此格式保留自1970年以来的秒数算术类型。

因此,用于这些目的的时间有1秒的粒度。

Rails不能命令hiddennow与随机项目之间至少延迟一秒钟,并且根本不会订购20套。