I'm doing some tests here using Rspec and I would like to assure that the controller is calling the log method in some actions. I'm also using mocha.
I would like something like this:
it "update action should redirect when model is valid" do
Tag.any_instance.stubs(:valid?).returns(true)
put :update, :id => Tag.first
controller.expects(:add_team_log).at_least_once
response.should redirect_to(edit_admin_tag_url(assigns[:tag]))
end
is there something to use as the 'controller' variable? I tried self, the controller class name...
I just got helped with this. For testing controllers, you'd nest your specs inside a describe which names the controller. (The spec should also be in the Controllers folder)
describe ArticlesController do
integrate_views
describe "GET index" do
...
it "update action should redirect when model is valid" do
...
controller.expects(:add_team_log).at_least_once
...
end
end
end
I think you want #controller instead of controller. Here's an example from my test suite:
it "delegates to the pricing web service" do
isbn = "an_isbn"
#controller.expects(:lookup)
.with(isbn, anything)
.returns({asin: "an_asin"})
get :results, isbn: isbn
assert_response :success
end
Related
So I am pretty new to testing with RSPEC
I am just testing the rendering of my controller like so:
describe "GET job" do
it "renders the jobs view" do
get :jobs
expect(response).to render_template :jobs
end
However my view (jobs) is a folder, not a template so the above dosnt work. How do i test to see if the response is going to the jobs view folder. inside my jobs view folder i have many different files.
My customer controller action looks like so:
def jobs
#jobs = #customer.jobs
end
To test that the template foobar inside app/views/jobs/ is rendered you should use this code:
describe "GET job" do
it "renders the jobs view" do
get :jobs
expect(response).to render_template :foobar
end
If you are not testing JobsController and would like to make sure that it still renders app/views/jobs/foobar then you should change it to this line:
expect(response).to render_template("jobs/foobar")
Ideally, in rspec controller test view rendering has been stubbed by default. To check view rendering in controller specs you have to do as follows:
describe "GET job" do
render_views
it "renders the jobs view" do
get :jobs
expect(response).to render_template("jobs/foobar")
end
where render_views will make render respective views of a controller action.
I have some controllers that are in subdomains of the controllers folder.
for example, i have a controller in app/controllers/api/v1/offers_controller.rb that looks like this:
class Api::V1::OffersController < ApplicationController
respond_to :json
def index
...some code here
end
end
I tried putting a controller in spec/controllers/api/v1/offers_controller.rb that looks like this:
require 'spec_helper'
descripe Api::V1::OffersController do
describe "GET 'index'" do
it "returns http success" do
get 'index'
response.should be_success
end
end
end
however, when I run rspec spec, this test does not get run at all. I also tried putting it in the spec/controllers directory, named api_v1_offers_controller.rb, and the test is still not run.
How can I write RSpec tests for these types of controllers?
It actually seems it was a mistake it how I named the file. it seems all RSpec tests need to end it _spec
I have an Ruby on Rails 3 admin_controller with the default set of CRUD, index and so on methods. I'd like to test each of these for certain assertions with rspec.
Like response.should render_template("layouts/some_layout") or tests that it should require login.
Copy-pasting that test into the group of tests for each method is a lot of duplication. IMO it makes little sense to have an
it 'should require login' do
Duplicated several times troughout that test.
Is there a simple way to run a test on a list of methods? Say defined_methods.each do |method| it 'should' .... of some sort?
Is this a good way in the first place? Or am I taking a wrong route in the first place?
Given that you really want all those assertions, have you considered shared example groups?
shared_examples_for "an action that requires authentication" do
it "should render successfuly" do
sign_in(user)
response.should be_success # or whatever
end
it "should deny access" do
# don't sign_in the user
# assert access was denied
end
end
shared_examples_for "another behaviour" do
# ...
end
let(:user) { create_user }
describe "#index" do
before(:each) { get :index }
it_behaves_like "an action that requires authentication"
it_behaves_like "another behaviour"
end
describe "#show" do
before(:each) { get :show }
it_behaves_like "an action that requires authentication"
end
# ...
Of course before writing large number of specs for a basic functionality you should always check if it isn't already tested by the library that is providing the functionality (e.g. checking for the rendered template, if it is handled by rails's implicit rendering, might be a bit overkill).
If you wanted to go down the route of iteratively testing each public method in the controller, you could do something like:
SomeController.public_instance_methods(false).each do |method|
it "should do something"
end
However, I think a shared example group (see about half way down this page: http://rspec.info/documentation/) would be prettier. If it were extracted so it could be used across all your controller specs, it'll be even nicer..
shared_examples_for "admin actions" do
it "should require login"
end
Then in each controller spec:
describe SomeController do
it_should_behave_like "admin actions"
end
Just add it to your test_helper.rb, something like:
def requires_login
...
end
i am working in Rspec of ROR..
I am trying to test my controllers using RSpec.i am having a Users controller with functions like new , tags, etc..
i created a file under spec/users_controller_spec.rb
and added the test cases as.
require 'spec_helper'
describe UsersController do
integrate_views
it "should use UsersController" do
controller.should be_an_instance_of(UsersController)
end
describe "GET 'new'" do
it "should be successful" do
get 'new'
response.should be_success
end
it "should have the title" do
get 'new'
response.should have_tag("title", "First app" )
end
end
end
which gets pass.
But when i add a test case for tags ..
like
describe "GET 'tags'" do
it "should be successful" do
get 'tags'
response.should be_success
end
end
this results in an error as
F...
1)
'UsersController GET 'tags' should be successful' FAILED
expected success? to return true, got false
why it is coming like this ?? i am very new to ROR and cant find the reason of why i am getting this error..
How to make this pass .
Also i tried the Url
http://localhost:3000/users/tags which is running for me .. But on testing using $spec spec/ i am getting the error ..
Your test may be failing for any number of reasons. Does the route require an ID in the parameter hash? Is the controller action redirecting? Is the controller raising an error?
You'll need to look at the controller code /and/or routes.rb to discover the cause of the failure. Take note of before filters in the controller, which may not allow the action to be reachable at all.
You need to add custom routes that are not within the default 7 routes. Assuming you have resources :users within your routes you will need to modify it. I'm also assuming that your tags route is unique to individual users.
resources :users do
member do
# creates /users/:user_id/tags
get :tags
end
end
And in your RSpec test you would call it like
describe '#tags' do
user = create :user
get :tags, user_id: user.id
end
If the route is not to be unique per user the other option is a collection route, something like:
resources :users do
collection do
# creates /users/tags
get :tags
end
end
I'm new to rails and I'm trying to test a controller with rspec. My first test is when the show action is invoked, it should lookup a Category by url.
The problem is when I add the stubbing code, I get the following error:
undefined method `find' for #
my test looks like this:
require 'spec_helper'
describe CategoriesController do
describe "GET /category-name/" do
before(:each) do
#category = mock_model(Category)
Category.stub!(:find).with(:first, :conditions => ["url = :url", {:url => "category-name"}]).and_return(#category)
end
it "should find the category by url" do
controller.show
Category.should_receive(:find).with(:first, :conditions => ["url = :url", {:url => "category-name"}]).and_return(#category)
end
end
end
Your call to the request should be after any should_receive. It's a tense thing. So it kind of reads like this, "Category should receive something, when this happens". "This happens" refers to the request.
it "should find the category by url" do
Category.should_receive(:find).with...
get "show", { your params, if you're sending some in }
end
Also, you want to go the way of a request vs calling the controller method itself, for this particular test at least.
So
post "action_name"
get "action_name"
update "action_name"
delete "action_name"
instead of
controller.action_name