我在测试中遇到了这个问题。假设我有两个模型,User和Post,其中用户has_many:posts。
我正在尝试找出一个包含如下内容的代码块:
user = User.find(123)
post = user.posts.find(456)
我知道如何模拟
User.find
和user.posts
部分。 user.posts
模拟返回一个Post对象数组。当到达.find(456)
部分时,一切都因no block given
异常而分解。所以我的问题是:
user.posts
模拟的结果如何返回,以便.find(456)
方法起作用? User.first.posts.class
表示它是Array,但是显然还有其他一些功能可以使AR风格的find调用正常工作。我对在返回的对象上模拟出find方法的前景并不感到高兴。PS在您建议停止 mock 和使用固定装置/使用必要的数据播种测试数据库这一显而易见的好答案之前,这里有个重点:传统方案。 User和Post都在数据库 View 而不是表上工作,并且更改它以使其成为测试数据库中的表对我来说似乎是错误的。
最佳答案
问题是user.posts
实际上不是简单的Array
;这是一个关联代理对象。 stub 的方式可能是这样的(尽管确切的语法取决于您所使用的模拟框架):
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)
方法中 stub 。