代码之家  ›  专栏  ›  技术社区  ›  Brian Deterling

在ActiveRecord单元测试中处理查询缓存是否重要?

  •  1
  • Brian Deterling  · 技术社区  · 14 年前

    在休眠的世界中,通常可以让单元测试看起来通过,但实际上有一些错误不会出现,因为您处理的是缓存数据。例如,可以将父级及其子级保存为级联保存。如果在保存并测试子集合的大小后重新查询父集合,则看起来正常。但实际上,Hibernate并没有拯救孩子,而是缓存了家长,所以你看到的是未被拯救的孩子。解决这个问题的一种方法是清除保存和查询之间的会话缓存,这样您就知道数据直接来自数据库。

    这是ActiveRecord的问题吗?如果我保存了一个模型,然后在同一个测试中查询它,是否可能我实际上不是从数据库而是从查询缓存中获取数据?我没有看到任何样本测试试图解决这个问题,所以我想知道是否有什么东西使它成为一个非问题?

    2 回复  |  直到 14 年前
        1
  •  1
  •   Gdeglin    14 年前

    对。根据编写测试的方式,Rails查询缓存有时可能会干扰。有时,Rails足够智能,可以跟踪何时需要清除缓存(当对象之间存在明显的关联时),但下面是一个不按预期工作的示例:

    user.posts.should == []
    Post.create(:user_id => user.id)
    user.posts.size.should_not == [] # Fails, since the original query was cached.
    

    通常,如果在同一测试中两次执行同一查询,则应调用。在尝试执行第二个查询之前,请重新加载数据。就像这样:

    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
  •  0
  •   Toby Hede    14 年前

    我从来没有遇到过ActiveRecord的问题。我的理解是缓存只在读取时进行,所以总是执行保存。