[英]How to test controller actions with complicated queries?
Supposing I have the following action: 假设我执行以下操作:
def index
@posts = Post.joins(:tags).where(:tags => {:id => params[:tag_id]})
end
It exposes @posts
to the view, which will display every post with the given tag. 它将@posts
暴露给视图,该视图将显示具有给定标签的每个帖子。
Everything works fine, but I'm stuck trying to figure out the best way to test it. 一切正常,但我一直在努力找出测试它的最佳方法。
I don't really like mocking, since it could brake the test if I changed that line to: 我真的不喜欢嘲笑,因为如果我将该行更改为:
@posts = Post.where(:tags => {:id => params[:tag_id]}).joins(:tags)
I don't really want to hit the database, as it'd reduce the test speed, but I'm considering extracting the query to a method inside the model, and test it there if it's the only way to do it. 我真的不想打数据库,因为它会降低测试速度,但是我正在考虑将查询提取到模型内部的方法,并在其中进行测试(如果这是唯一的方法)。
EDIT: Yes, I know I could use Tag.find(params[:tag_id])
in this case, but this is not what the question is about. 编辑:是的,我知道在这种情况下可以使用Tag.find(params[:tag_id])
,但这不是问题所在。 I just didn't want to introduce another model in the query and make it harder to explain deviating the focus from the real problem, which is: Should we keep complex queries in the controller? 我只是不想在查询中引入其他模型,而使解释更难于将焦点与实际问题区分开来,即:是否应该在控制器中保留复杂的查询? If so, what's the best way to test it? 如果是这样,最好的测试方法是什么?
This is what i like to do. 这就是我喜欢做的。 Generally, i like to integrate database testing inside my tests( though some would disagree, i personally like it ). 通常,我喜欢将数据库测试集成到我的测试中(尽管有些人会不同意,我个人很喜欢)。 I would create like 3 factories(:post) and maybe some tags as dummy data and then i would call on the controller and check whether the received @posts is what i would expect. 我会创建3个factory(:post),也许还会创建一些标记作为虚拟数据,然后我将调用控制器并检查接收到的@posts是否符合我的期望。
So, according to the comments extracting to the model is the best thing to do. 因此,根据注释提取到模型是最好的方法。 That's how I did it: 我就是这样的:
post.rb: post.rb:
class Post
scope :tagged_as, lambda {|tag_id| where(:tag_id => tag_id)}
end
posts.yml: posts.yml:
one:
title: Post 1
tags: one, three
two:
title: Post 2
tags: two, three
post_test.rb: post_test.rb:
test 'find by tag' do
posts = Post.tagged_as(tags(:one))
assert_includes posts, posts(:one)
refute_includes posts, posts(:two)
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.