3

Let's say we have some piece of code like so:

def index
  @posts = Post.where(:status => ACTIVE)
  if params[:s]
    @posts = Post.where("title like ?", "%#{params[:s]}%").order("title asc")
  else
    @posts = Post.limit(20).order("date desc")
  end
end

When specing this action we could either write a stub chain for every example but this way it restrains us a lot if we want to focus somewhere else.

What's the best way to stub a complex Arel query for RSpec when you don't know the order or how many of the methods will be called?

NOTE: I was looking at Stubbing Chained Queries in Rails 3 and Rspec and what I think I want is something like stub_chain_with_indifferent_order(:where, :order, :limit).

Community
  • 1
  • 1
Kostas
  • 8,356
  • 11
  • 47
  • 63
  • If you really want to spec queries, stubbing them is usually the wrong answer. You want to test behavior, not which parameters you gave the method. Load your db with data and **run** the query against the data, then check if it really conforms with your criteria. – Maurício Linhares Aug 01 '11 at 14:01
  • 1
    What I am trying to do is test for things like "should have assigned @posts" or "render one li per post in @posts" where stubbing is really useful to avoid the db overhead. – Kostas Aug 01 '11 at 14:07

1 Answers1

2

This might be the code telling you that you are doing this at the wrong level. Which is something I really like about the MOCK ALL THE THINGS(!!) philosophy of RSpec: if it's getting hard to mock, maybe your design is wrong.

For example, I might refactor your code to be:

def index
  @posts = Post.posts_for(:like => params[:s], :order => (params[:s] ? "title asc" : "date desc")
end

(Or something slightly better given your domain.)

Then you can mock out Posts.posts_for, a simple method call, instead of trying to mock a ton of AR chained methods.

RyanWilcox
  • 13,890
  • 1
  • 36
  • 60
  • 3
    I like where you are coming from here, but I feel slightly uncomfortable with making a catch-all method. The whole idea of arel (which I am not going to advocate or antagonize, it is simply the DSL I have been handed) is that you drive queries through incremental units of behavior articulated by method calls. That being said, I'll agree my code is seeming kinda smelly, and is losing some of the domain language of the problem my application is trying to solve. – Steve Y Aug 01 '12 at 20:17