Jun 13 2008

Testing Merb controllers

One of the features that attracted me to Merb was the ability to test controllers in an independent, lightweight manner. In essence, this involves instantiating a controller class, passing it a FakeRequest and calling methods (actions) on the controller object.

Let's consider a controller which collaborates with a service.

class Foo < Merb::Controller
  def bar
    service = Service.new
    session[:metal] = service.metal
    @zz = service.rock
    render
  end
end

class Service
  def rock
    "zz top"
  end

  def metal
    "metallica"
  end
end

Testing the controller is as straightforward as creating an instance of Foo, setting it up, calling bar and interrogating it.

class FooTest < Test::Unit::TestCase
  def setup
    @foo = Foo.new(Merb::Test::RequestHelper::FakeRequest.new)
    @foo.request.session = {}
    @foo.bar
  end

  def test_puts_metallica_in_session
    assert_equal("metallica", @foo.session[:metal])
  end

  def test_assigns_zz_top
    assert_equal("zz top", @foo.assigns(:zz))
  end
end

I'm not sure why the controller's session variable has to be explicitly initialized, had it been present would make testing slightly cleaner.