How to make the test name match the controller name? - ruby-on-rails

I have this users_controller
class Api::V1::UsersController < ApplicationController
respond_to :json
def show
respond_with User.find(params[:id])
end
end
The file is in app/controllers/api/v1/
And my test is :
class Api::V1::UsersControllerTest < ActionController::TestCase
test '#show displays the specific user' do
#user = FactoryGirl.build(:user)
get :show, id: #user.id
assert_response :success
end
end
The file is in test/controllers/api/v1
When I run the test I get this error :
NameError: uninitialized constant Api
/Users/Ahmad/rails_apps/json_api/test/controllers/api/v1/users_controller_test.rb:1:in `<top (required)>'
What's going on?
Thanks

I think you miss
require 'test_helper'
at the top of your file. Give a try.

Related

functional tests admin section rails

I have a question concerning a functional test in rails.
For the front section, the actions are only index and show
#app/controller/themes_controller_rb
class ThemesController < ApplicationController
def index
#themes = Theme.active
end
def show
#theme = Theme.find(params[:id])
end
def new
end
end
and the test
#test/integration/theme_controller_test.rb
require 'test_helper'
class ThemesControllerTest < ActionController::TestCase
def setup
#theme = create(:theme)
end
test "should assign variable on index" do
get :index
assert_response :success
assert_not_nil assigns(:themes)
end
test "should show a theme" do
get :show, {'id' => #theme}
assert_response :success
assert_not_nil assigns(:theme)
end
end
No problem so far
For the admin section, all the CRUD actions exists so again index and show
#app/controllers/admin/themes_controller.rb
class Admin::ThemesController < Admin::AdminController
layout 'admin/admin'
before_action :admin_user
def index
#themes = Theme.all
end
def show
#theme = Theme.find(params[:id])
end
end
and the tests are the same
#test/controllers/admin/theme_controller_test.rb
require 'test_helper'
class Admin::ThemesControllerTest < ActionController::TestCase
def setup
#theme = create(:theme)
end
test "should assign variable on index" do
get :index
assert_response :success
assert_not_nil assigns(:themes)
end
test "should show a theme" do
get :show, {'id' => #theme}
assert_response :success
assert_not_nil assigns(:theme)
end
end
but for those latest tests, I have a 302 response instead of succes
FAIL["test_should_assign_variable_on_index", Admin::ThemesControllerTest, 2016-03-16 06:50:16 +0000]
test_should_assign_variable_on_index#Admin::ThemesControllerTest (1458111016.61s)
Expected response to be a <success>, but was <302>
test/controllers/admin/themes_controller_test.rb:11:in `block in <class:ThemesControllerTest>'
FAIL["test_should_show_a_theme", Admin::ThemesControllerTest, 2016-03-16 06:50:16 +0000]
test_should_show_a_theme#Admin::ThemesControllerTest (1458111016.62s)
Expected response to be a <success>, but was <302>
test/controllers/admin/themes_controller_test.rb:18:in `block in <class:ThemesControllerTest>'
What do I do wrong ? Thanks for help :)

Why rails minitest testcases are failing

My posts_controller_Test.rb file:
# test/controllers/posts_controller_test.rb
require 'test_helper'
class PostControllerTest < ActionController::TestCase
def setup
#post = Post.new
end
test 'should get index' do
get :index
assert_response :success
assert_not_nil assigns(:posts)
end
end
My post_controller File
class PostsController < ActionController::Base
before_action :authenticate_user!
def index
#post = current_user.posts.paginate(page: params[:page], per_page: 5)
respond_to do |format|
format.html
format.json { render json: #post }
end
end
def new
#post = Post.new
end
def create
#post = current_user.posts.build(post_param)
if #post.save
redirect_to action: 'index'
else
render 'new'
end
end
Why my test cases are failing? Is it because I have authenticate_user! condition? I also have .yml file and tried to test with it but after initializing with .yml data I am getting RuntimeError: #controller is nil: make sure you set it in your test's setup method.
yml file
one:
data 2
value: 3
user_id: 1
name: 'test'
.yml has everything what i have required in
params.require(:post).permit(:data, :value, :name) and obvious `user` for foreign key reference
Edit -1
After the suggestion of inheriting with ApplicationController
Got this new error:
NameError: uninitialized constant ApplicationController::Base
app/controllers/posts_controller.rb:3:in `<top (required)>'
app/controllers/posts_controller.rb:3:in `<top (required)>'
this is my line 3:
class PostsController < ApplicationController::Base
Edit-2
class PostsController < ApplicationController
got this:
NoMethodError: undefined method `authenticate!' for nil:NilClass
The error is because you've inherited your controller from the wrong class. Inherit from ApplicationController instead:
class PostsController < ApplicationController
...
end

Controller Spec #Show Action: exoected: [Object], got: nil Error - RSpec 3

I am going through Aaron Sumner's Everyday Rails Testing with RSpec (3) book, and can't get passed the following step:
I am trying to spec out a users#show action with:
users_controller_spec:
...
describe 'GET #show' do
it "assigns the requested contact to #user" do
user = create(:user)
get :show, id: user.id
expect(assigns(:user)).to eq user
end
it "renders the :show template" do
user = create(:user)
get :show, id: user.id
expect(response).to render_template :show
end
end
...
users_controller:
class UsersController < ApplicationController
before_action :authenticate
before_action :set_user, only: [:show]
### Read:
def show
...
end
private
def set_user
#user = User.find(params[:id])
end
end
application_controller helpers:
def authenticate
redirect_to home_path, alert: 'Please log in first' if current_user.nil?
end
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
Errors:
Failures:
1) UsersController GET #show assigns the requested user to #user
Failure/Error: expect(assigns(:user)).to eq user
expected: #<User id: 1, ...">
got: nil
(compared using ==)
# ./spec/controllers/users_controller_spec.rb:10:in `block (3 levels) in <top (required)>'
2) UsersController GET #show renders the :show template
Failure/Error: expect(response).to render_template :show
expecting <"show"> but rendering with <[]>
# ./spec/controllers/users_controller_spec.rb:17:in `block (3 levels) in <top (required)>'
Your issue comes from before_action :authenticate either you need to set yourself as authenticated in the specs or you need to skip authentication for the show action.
You would normally test like:
context 'when logged in' do
before(:each) do
set_as_logged_in
end
# your specs
end
where the set_as_logged_in method would differ based on the way you are authenticating. Then you could also have a 'when not logged in' context to verify the action behaves as expected when you are not logged in.

Rspec, how do I test if a response renders a template

I'm new to rspec and writing test. I need to write a test for the show action of my VideosController. Here is my test
describe VideosController do
describe "GET show" do
it "renders the show template" do
video = Video.create(title: "Game of Thrones", description: "A very awesome show!")
get :show, id: video.id
expect(response).to render_template(:show)
end
end
end
When I run this I get this error
1) VideosController GET show renders the show template
Failure/Error: expect(response).to render_template(:show)
expecting <"show"> but rendering with <[]>
What am I missing here?
EDIT: VideosController
class VideosController < ApplicationController
before_action :require_user
def show
#video = Video.find(params[:id])
end
def search
#search_phrase = params[:search_term]
#search_result = Video.search_by_title(#search_phrase)
end
end
For setting the user, controller tests are meant to be isolated from other aspects of the app. So really you can simply stub the user. Provided you're using a method in your application controller like:
def current_user
#current_user ||= User.find session[:user_id]
end
Then you can just stub it:
controller.stub(current_user: User.create(email: "test#example.com", password: "abc123", password_confirmation: "abc123"))
Adjust the user params to your need. Also instead of invoking active record directly, have a look at: http://github.com/thoughtbot/factory_girl.
So what happens there is when the controller invokes current_user, it returns the user record.

How can I test ActiveRecord::RecordNotFound in my rails app?

I have this code in my controller and want to test this code line with a functional test.
raise ActiveRecord::RecordNotFound if #post.nil?
which assert method should I use?
I use the built-in rails 2.3.5 test framework.
I tried it with this code:
test "should return 404 if page doesn't exist." do
get :show, :url => ["nothing", "here"]
assert_response :missing
end
but it doesn't work for me. Got this test output:
test_should_return_404_if_page_doesn't_exist.(PageControllerTest):
ActiveRecord::RecordNotFound: ActiveRecord::RecordNotFound
app/controllers/page_controller.rb:7:in `show'
/test/functional/page_controller_test.rb:21:in `test_should_return_404_if_page_doesn't_exist.'
There are two things you can do. The first is to let ActionController provide the default action when it rescues ActiveRecord::RecordNotFound:
class PostsControllerTest < ActionController::TestCase
test "raises RecordNotFound when not found" do
assert_raises(ActiveRecord::RecordNotFound) do
get :show, :id => 1234
end
end
end
Using this method, you can't assert what gets rendered. You have to trust Rails/ActionController not to change behaviour.
An alternative, which I've sometimes used, is this:
class PostsControllerTest < ActionController::TestCase
test "renders post_missing page, and returns 404" do
get :show, params: { :id => 1234 }
assert_response :not_found
assert_template "post_missing"
end
end
class PostsController < ApplicationController
def show
#post = current_user.posts.find_by!(slug: params[:slug])
end
rescue_from ActiveRecord::RecordNotFound do
render :action => "post_missing", :status => :not_found
end
end
You should read more about #rescue_from on the ActiveSupport API.
For simplicity, I usually go with my 1st solution though.

Resources