【问题标题】:Is it important to deal with query caching in ActiveRecord unit tests?在 ActiveRecord 单元测试中处理查询缓存是否重要?
【发布时间】:2010-02-23 03:03:08
【问题描述】:
在 Hibernate 世界中,您通常可以进行单元测试,这些测试看似通过,但实际上存在未显示的错误,因为您正在处理缓存数据。例如,您可以保存一个父级及其子级,认为它正在级联保存。如果在保存后重新查询父集合并测试子集合的大小,它看起来没问题。但实际上 Hibernate 并没有保存孩子,而是缓存了父母,所以你正在查看未保存的孩子。解决此问题的一种方法是清除保存和查询之间的会话缓存,以便您知道数据直接来自数据库。
这是 ActiveRecord 的问题吗?如果我保存一个模型然后在同一个测试中查询它,我是否可能实际上不是从数据库中获取数据,而是从查询缓存中获取数据?我还没有看到任何尝试解决此问题的示例测试,所以我想知道是否有什么使它成为非问题?
【问题讨论】:
标签:
ruby-on-rails
unit-testing
activerecord
query-cache
【解决方案1】:
是的。根据您编写测试的方式,Rails 查询缓存有时会产生干扰。有时,rails 足够聪明,可以跟踪何时需要清除缓存(当对象之间存在明显关联时),但这里有一个不会按预期运行的示例:
user.posts.should == []
Post.create(:user_id => user.id)
user.posts.size.should_not == [] # Fails, since the original query was cached.
一般来说,如果您在同一个测试中执行同一个查询两次,您应该在尝试执行第二个查询之前对数据调用 .reload。像这样:
user.posts.should == []
Post.create(:user_id => user.id)
user.posts.reload
user.posts.size.should_not == []
根据我的个人经验,最好考虑另一种编写测试的方法,而不是使用上述方法。例如,这里有一个不受查询缓存影响的更好的写上面的方法:
lambda { Post.create(:user_id => user.id) }.should_change(user.posts, :count).by(1)
【解决方案2】:
我从来没有遇到过 ActiveRecord 的问题。我的理解是缓存只在读取时,所以总是执行保存。