Continuation of Last time
Controller testing in RSpec can be replaced by model testing and integration testing, so there aren't many opportunities to use it. Recently, with the introduction of system specs, which are more advanced integration tests, the number of controller specs has been further reduced. However, I think that it may be touched by the maintenance of the existing program, so I will summarize it only lightly.
Tests if the status of the response is successful. First, generate a spec file.
$ rails g rspec:controller home
spec/controllers/home_controller_spec.rb will be generated.
Test if the controller returns a successful response to the request.
spec/controllers/home_controller_spec.rb
require 'rails_helper'
RSpec.describe HomeController, type: :controller do
de
describe "#index" do
it "responds successfully" do
get :index
expect(response).to be_success
end
end
end
The response is an object that holds all the application data that should be returned to the browser. be_success is a matcher that checks if the response status is successful (200) or not.
You can use have_http_status if you want to see a specific HTTP response code.
spec/controllers/home_controller_spec.rb
require 'rails_helper'
RSpec.describe HomeController, type: :controller do
de
describe "#index" do
it "responds a 200 response" do
get :index
expect(response).to have_http_status "200"
end
end
end
I will write the specifications of the projects controller. This controller has a common CRUD structure that allows only logged-in users to work with projects associated with them.
$ rails g rspec:controller project
As before, we'll first test for a successful response, but controller actions that require authentication need to be prepared in advance.
There are two main preparations,
Devise provides a helper that simulates a user's login state for controller actions that require authentication, and uses this helper when running tests. However, RSpec doesn't load this helper by default, so I'll add some settings to make it available.
spec/rails_helper.rb
#Add this one line
config.include Devise::Test::ControllerHelpers, type: :controller
With this setting, you can use Devise's helper module in the controller specifications.
If you send a request while the user is not logged in, you will get a redirect (302) back to the login page, so you need to be logged in as a test setup.
Even if you describe the login process in the specifications, it will work, but since the login process is performed frequently, it is a must to create a helper now.
#Login process tailored to each app
def sign_in(user)
cookies[:auth_token] = user.auth_token
end
Since the processing results of the Projects controller differ between the logged-in user and the guest user, prepare multiple test scenarios.
spec/controllers/projects_controller_spec.rb
require 'rails_helper'
RSpec.describe ProjectsController, type: :controller do
de
describe "#index" do
context "guest" do
it "returns a 302 response" do
get :index
expect(response).to have_http_status "302"
end
it "redirects to the sign_in page" do
get :index
expect(response).to redirect_to "users/sign_in"
end
end
context "logged_in" do
before do
@user = FactoryBot.create(:user)
end
it "responds successfully" do
sign_in @user
get :index
expect(response).to be_success
end
it "responds a 200 response" do
sign_in @user
get :index
expect(response).to have_http_status "200"
end
end
end
end
We will also test POST, PATCH, and DESTROY requests using the create action as an example. Don't forget input errors and tests.
spec/controllers/projects_controller_spec.rb
describe "#create" do
context "guest" do
it "returns a 302 response" do
project_params = FactoryBot.attributes_for(:project)
post :create, params: { project: project_params }
expect(response).to have_http_status "302"
end
it "redirects to the sign_in page" do
project_params = FactoryBot.attributes_for(:project)
post :create, params: { project: project_params }
expect(response).to redirect_to "/users/sign_in"
end
end
context "logged_in" do
before do
@user = FactoryBot.create(:user)
end
context "vaild attributes" do
it "adds a project" do
project_params = FactoryBot.attributes_for(:project)
sign_in(@user)
expect{
post :create, params: { project: project_params }
}.to change(@user.projects, :count).by(1)
end
end
context "invaild attributes" do
it "dose not add a project" do
project_params = FactoryBot.attributes_for(:project, :invalid)
sign_in(@user)
expect{
post :create, params: { project: project_params }
}.to_not change(@user.projects, :count)
end
end
end
end
We will also look at testing the process of returning data in formats such as CSV and JSON. With the code to send the request
format: :json
Specify the format with
expect(response.content_type).to eq "application/json"
You can test by specifying the format of the data returned in.
Recommended Posts