在RSpec测试中模仿ActiveRecord关系

时间:2010-01-29 10:15:41

标签: ruby activerecord rspec mocking

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

我正在尝试列出包含以下内容的代码块:

user = User.find(123)
post = user.posts.find(456)

我知道如何模拟User.finduser.posts部分。 user.posts mock返回一个Post对象数组。当它到达.find(456)部分时,一切都会因no block given异常而崩溃。

所以我的问题是:作为user.posts模拟的结果,我将返回什么,以便.find(456)方法对其起作用? User.first.posts.class说它是数组,但显然还有一些东西可以使AR风格的查找调用工作。我对于在返回的对象上模拟find方法的前景并不高兴。

PS在你建议明确和好的答案停止嘲笑和使用固定装置/使用必要的数据播种测试数据库之前,这里是catch:legacy scheme。 User和Post都在数据库视图之上工作而不是表,并且更改它以使它们成为测试数据库中的表似乎对我不利。

2 个答案:

答案 0 :(得分:16)

问题在于user.posts 实际上 是一个简单的Array;它是一个关联代理对象。存根的方式可能是这样的(虽然确切的语法取决于你正在使用的模拟框架):

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

然后在您的测试中,User.find(123)将返回@user@user.posts.find(456)将返回@post。如果您需要@user.posts在测试中更多地使用Array,则可以创建mock(Array)并存根[](index)方法。

答案 1 :(得分:7)