Controller Specs / Edits
Edited line 15 :
Note: not everyone agrees this is a good idea. But it’s good to know about this approach and why some people like it.
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.
Edited line 87 :
Edited line 38 :
Edited line 50 :
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.
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.
Edited line 65 :
Edited line 72 :
And the spec for an action with a parameter (if you really feel you have to stub display):
And the spec for an action with a parameter:
Edited line 95 :
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.
Notice that the request path and method are not specified anywhere. Merb 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.
Edited line 39 :
Edited line 39 :
Edited line 22 :
Edited line 34 :
Edited line 56 :
Edited line 75 :
Edited line 113 :
Edited line 114 :
Edited line 119 :
Edited line 123 :
Edited line 125 :
Edited line 129 :
Edited line 134 :
Edited line 139 :
Edited line 42 :
Edited line 19 :
Lets say we have an Articles controller with an index we want to spec:
class Articles < Application
class Articles < Application
Edited line 26 :
describe Articles do
Edited line 29 :
We could spec this index action to make sure it always fetches the articles from the database in descending order by date:
describe Articles do
Edited line 41 :
Edited line 44 :
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.
class Articles < Application
Edited line 46 :
Lets add a show action with an id parameter:
class Articles < Application
Edited line 58 :
describe Articles do
Edited line 61 :
And the spec for an action with a parameter:
describe Articles do
Edited line 77 :
Edited line 79 :
Notice that the request path and method are not specified anywhere. Merb 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.
Edited line 80 :
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.
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:
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
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.
Edited line 28 :
describe Articles do
describe Articles do
Edited line 46 :
class Articles < Application
class Articles < Application
Edited line 62 :
describe Articles do
describe Articles do
Edited line 20 :
class Articles < Application
class Articles < Application
Edited line 28 :
Edited line 32 :
Edited line 46 :
Edited line 52 :
Edited line 66 :
Edited line 70 :
Edited line 88 :
Edited line 22 :
Edited line 27 :
Edited line 33 :
Edited line 35 :
Edited line 37 :
Edited line 40 :
Edited line 45 :
Edited line 71 :
Edited line 73 :
Edited line 75 :
Edited line 79 :
Edited line 82 :
Edited line 87 :
Edited line 89 :
If your action’s behavior depends on the request method, the get, post, put, delete will allow you to fake the request method.
Edited line 48 :
class Articles < Application
def index
@articles = Article.all(:order => 'created_at desc')
display @articles
end
def show(id)
@article = Article.with_slug(id)
raise NotFound unless @article
display @article
end
end
And the spec for an action with a parameter:
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
Edited line 19 :
Lets say we have an Articles controller with an index we want to spec:
Edited line 32 :
We could spec this index action to make sure it always fetches the articles from the database in descending order by date:
Edited line 45 :
Edited line 50 :
Edited line 13 :
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.
Examples
Lets say we have an Articles controller with an index we want to spec:
class Articles < Application
def index
@articles = Article.all(:order => 'created_at desc')
display @articles
end
end
We could spec this index action to make sure it always fetches the articles from the database in descending order by date:
describe Articles do
describe "#index" do
it "should get all articles in descending order of date created" do
Article.should_receive(:all).with(:order => 'created_at desc')
dispatch_to(Article, :index)
end
end
end
Examples
Edited line 4 :
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.