Merb Wiki
Home
All Pages
New Page
Editing Controller Specs
Textile Enabled
| [[Page Name]] for internal links
h2. Overview Merb was designed so that a controller called by a test executes the same way as from a user's request. Controllers are instantiated with the entire request as an argument. This means calling an action can be handled by faking the request object, which is exactly what the controller helpers do. This also means that faked requests execute actions exactly the same way as real requests. h2. Keep In Mind Controller specs work best when the interaction with models have been completely stubbed out. Checkout the RSpec documentation for more info on how to stub & mock for your models. It is also a good idea to stub the *render* and *display* methods for your controller. These methods invoke the view, which should be left to the view specs. Note: not everyone agrees this is a good idea. But it's good to know about this approach and why some people like it. h2. Matchers. Merb core provides number of matchers for RSpec: * redirect * redirect_to (aliased as be_redirection_to) * be_success (aliased as respond_successfully) * be_missing (aliased as be_client_error) redirect_to takes :message option in case your action uses redirect with it. h2. Examples Lets say we have an *Articles* controller with an *index* we want to spec: <pre><code class="ruby"> class Articles < Application def index @articles = Article.all(:order => 'created_at desc') display @articles end end </code></pre> We could spec this *index* action to make sure it always fetches the articles from the database in descending order by date: <pre><code class="ruby"> describe Articles do describe "#index" do it "fetches all articles in descending order of date created" do Article.should_receive(:all).with(:order => 'created_at desc') dispatch_to(Articles, :index) do |controller| controller.stub!(:display) end end end end </code></pre> This will make sure the index action will always display the articles in descending order without actually querying the database or rendering the view, meaning you don't have to worry about populating the database from fixtures or rendering errors. It is not always the case so you can use fixtures and do not stub display so you can operate on response body to do some assertions. Lets add a *show* action with an id parameter: <pre><code class="ruby"> class Articles < Application def index @articles = Article.all(:order => 'created_at desc') display @articles end def show(id) begin @article = Article.with_slug(id) display @article rescue YourOrm::RecordNotFoundOrSomething raise NotFound end end end </code></pre> And the spec for an action with a parameter (if you really feel you have to stub display): <pre><code class="ruby"> describe Articles do describe "#show" do before(:each) do @article = mock(:article) end it "should display the article matching the slug id" do Article.stub!(:with_slug).with("slug").and_return @article dispatch_to(Articles, :show, :id => "slug") do |controller| controller.should_receive(:display).with(@article) end end end end </code></pre> Notice that the request path and method are not specified anywhere. Merb dispatch_to helper allows you to invoke an action without specifying the request method, keeping your routes removed from your controller tests. If you want to spec your routes (and you always do), Merb provides helpers & matchers specifically for testing your routes. See the [Routing Specs] for more. If your action's behavior depends on the request method, the *get*, *post*, *put*, *delete* will allow you to fake the request method and *NOT* bypassing routing. h2. Taming Spec Complexity Sometimes your specs can grow quite complex. It's often handy to abstract away some complexity. Here are some tips for handling complexity with abstraction. h3. Handling Requests Did you notice in the above examples the frequent usage of *dispatch_to*? It's sometimes best to wrap up the test request to your controller so that each example in your spec is making the same sort of request. For example: <pre><code class="ruby"> describe "requesting /pages with GET" do before(:each) do Page.stub!(:all).and_return(pages) end def do_get dispatch_to(Pages, :index) do |controller| controller.stub!(:display) end end it "should be successful" do do_get.should be_successful end it "should load all page records" do Page.should_receive(:all).and_return(pages) do_get.assigns(:pages).should == pages # pages is defined elsewhere end it "should display all pages" do dispatch_to(Pages, :index) do |controller| controller.should_receive(:display).with(pages) # pages is defined elsewhere end end end </code></pre> The method *do_get* neatly summarizes the most common request we're making in our spec, handles any stubs, and has a wonderfully descriptive name to describe what's happening. Notice in the last example in the above spec that we don't _have_ to use *do_get*. In this last example we hand write our usage of *dispatch_to* to ensure that a particular method is being called.
Submit
Recent Activity
Home
was updated
Home
was updated
deploying-a-merb-application-to-a-jee-container-us
was updated
deploying-a-merb-application-to-a-jee-container-us
was updated
Merb Developers available for work
was updated
deploying-a-merb-application-to-a-jee-container-us
was updated
deploying-a-merb-application-to-a-jee-container-us
was updated
deploying-a-merb-application-to-a-jee-container-us
was updated
deploying-a-merb-application-to-a-jee-container-us
was updated
Home
was updated