Testing Merb controllers with RSpec

I've been trying out Merb recently, and I'm liking it. However, I've spent a lot of time stumbling around the interweb looking for examples of what I've been trying to achieve. So far I've been coming up short. The Merb API docs are good, but you can't beat a good example.

Just so you know, I'm currently using Merb 0.9.2.

When you create your controller with merb-gen controller MyController, the generated RSpec file (in the spec/controllers directory) contains something like this:

describe MyController, "index action" do
  before(:each) do
    dispatch_to(MyController, :index)
  end
end

In order to unit test the controller you need to be able to call RSpec's should method on it. This is well and good, but the API docs don't make it particuarly obvious how you get hold of the controller itself.

There's obviously going to be a common idiom for setting this up. Could Google find it? Nope. But IRC could. do_request returns a controller, so you can modify the before block ever so slightly:

describe MyController, "index action" do
  before(:each) do
    @controller = do_request(MyController, :index)
  end

  it "should render successfully" do
    @controller.should render_successfully
  end
end

As the Merb docs point out, because do_request bypasses the router it's ideally suited for unit testing a controller. You choose the method, you set your expectations, you write your test.

Talking of which, just how do you set expectations on the controller for calls that take place during the do_request call? The syntax is rather neat; you pass a block, like this:

before(:each) do
  @controller = do_request(MyController, :index) do |controller|
    controller.should_receive(:render).with(:new)
  end
end

Update: Almost as soon as I posted this I discovered that there's a great page on the Merb wiki about testing Merb with rspec...

I love feedback and questions — please feel free to get in touch on Mastodon or Twitter, or leave a comment.