Ruby RSpec测试中模拟ActiveRecord关系beheavior

Ruby RSpec测试中模拟ActiveRecord关系beheavior,ruby,activerecord,rspec,mocking,Ruby,Activerecord,Rspec,Mocking,我在测试中遇到了这个问题。假设我有两个模型,User和Post,其中User有很多:posts 我正在尝试指定一个代码块,其中包含以下内容: user = User.find(123) post = user.posts.find(456) 我知道如何模仿用户。查找和用户。发布部分。user.postsmock返回一个Post对象数组。当它找到(456)零件时,所有的东西都会分解,没有任何块出现异常 所以我这里的问题是:user.postsmock的结果是什么,这样.find(456)方法就可

我在测试中遇到了这个问题。假设我有两个模型,User和Post,其中User有很多:posts

我正在尝试指定一个代码块,其中包含以下内容:

user = User.find(123)
post = user.posts.find(456)
我知道如何模仿
用户。查找
用户。发布
部分。
user.posts
mock返回一个Post对象数组。当它找到(456)
零件时,所有的东西都会分解,没有任何块出现异常

所以我这里的问题是:
user.posts
mock的结果是什么,这样
.find(456)
方法就可以工作了
User.first.posts.class
说它是数组,但显然还有更多东西使AR风格的find调用起作用。对于在返回的对象上模拟find方法的前景,我并不感到高兴


PS在你提出一个明显而好的答案之前,停止嘲弄和使用夹具/用必要的数据植入测试数据库,这里有一个陷阱:遗留方案。用户和Post都是在数据库视图之上工作,而不是在表之上工作,并且在我看来,将其更改为测试数据库中的表是错误的。

问题在于
User.posts
实际上不是一个简单的
数组
;它是一个关联代理对象。存根的方法可能是这样的(尽管确切的语法取决于您使用的模拟框架):


然后在测试中,
User.find(123)
将返回
@User
,而
@User.posts.find(456)
将返回
@post
。如果您需要
@user.posts
在测试中更像
数组
,您可以创建一个
mock(Array)
并存根
[](index)
方法。

您可以查看RSpec提供的存根链方法


更新:根据Ryan2Johnson 9更新的文档是:

这是我不想做的“丑陋”的方式,但是你提到的“关联代理对象”为我提供了我丢失的关键字,搜索它导致了我正在寻找的,谢谢@Toms,如果您的解决方案在这些答案中是唯一的,那么您可以将其添加为另一个答案。我想看看你是怎么解决的。丑陋的方式,一个接一个的嘲弄。我很高兴知道这一点——这不是我第一次遇到这种情况,这让我很困扰。我和你一样痛苦。当测试开始看起来像OO意大利面条时,您开始认为一定有更好的方法。如果您的测试开始变得难看,可能是时候重构一些代码了。我发现一种常见的重构很有用(不是在这种特殊情况下),就是将一系列嵌套的作用域封装在一个模型类方法中
def setup
  @user = mock(User)
  User.stub(:find).with(123).return(@user)
  user_posts = mock(Object)
  @user.stub(:posts).return(user_posts)
  @post = mock(Post)
  user_posts.stub(:find).with(456).return(@post)
end