问题描述
我正在尝试在 Rails 应用程序中运行控制器测试。
控制器代码
这里是控制器测试的代码(/app/controllers/projects_controller.rb
):
class ProjectsController < ApplicationController
## START: show
def show
@project = Project.find(params[:id])
respond_to do |format|
format.html {}
format.js { render json: @project.as_json(root: true,include: :tasks) }
end
end
## END: show
def new
@project = Project.new
end
def index
@projects = Project.all
end
## START: create
def create
@workflow = CreatesProject.new(
name: params[:project][:name],task_string: params[:project][:tasks])
@workflow.create
if @workflow.success?
redirect_to projects_path
else
@project = @workflow.project
render :new
end
end
## END: create
end
控制器测试
这是终端显示错误 (/spec/controllers/projects_controller_spec
) 的测试:
require "rails_helper"
RSpec.describe ProjectsController,type: :controller do
describe "create" do
it "calls the workflow with parameters" do
workflow = instance_spy(CreatesProject,success?: true)
allow(CreatesProject).to receive(:new).and_return(workflow)
post :create,params: {project: {name: "Runway",tasks: "start something:2"}}
expect(CreatesProject).to have_received(:new)
.with({name: "Runway",task_string: "start something:2"})
end
end
end
我添加了更多测试
以下是我遵循的说明:
- 我将此添加到 Gemfile:
gem 'devise'
- 在
config/environments/development.rb
中,添加了一些默认邮件程序选项config.action_mailer.default_url_options = { host: 'localhost:3000' }
。 - 给 config.routes.rb 一个根路由——例如,通过将根添加到: “项目#index”。
- 在
app/views/layouts/application.html.erb
文件中添加了以下内容:
<!DOCTYPE html>
<html>
<head>
<title>Gatherer</title>
<%= csrf_Meta_tags %>
<%= stylesheet_link_tag 'application',media: 'all','data-turbolinks-track':
'reload' %>
<%= javascript_pack_tag 'application','data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag "projects" %>
</head>
<body>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
</html>
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable,:lockable,:timeoutable and :omniauthable
devise :database_authenticatable,:registerable,:recoverable,:rememberable,:trackable,:validatable
end
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers,type: :controller
config.include Devise::Test::ControllerHelpers,type: :view
config.include Devise::Test::IntegrationHelpers,type: :system
config.include Devise::Test::IntegrationHelpers,type: :request
end
module ActionController
class TestCase
include Devise::Test::ControllerHelpers
end
end
module Actiondispatch
class IntegrationTest
include Devise::Test::IntegrationHelpers
end
end
require "rails_helper"
RSpec.describe "with users and roles" do
def log_in_as(user)
visit new_user_session_path
fill_in("user_email",with: user.email)
fill_in("user_password",with: user.password)
click_button("Log in")
end
let(:user) { User.create(email: "test@example.com",password: "password") }
it "allows a logged-in user to view the project index page" do
log_in_as(user)
visit(projects_path)
expect(current_path).to eq(projects_path)
end
it "does not allow a user to see the project page if not logged in" do
visit(projects_path)
expect(current_path).to eq(user_session_path)
end
end
- 为了使测试通过,我将其添加到
app/controllers/application_controller.rb
:
module ActionController
class TestCase
include Devise::Test::ControllerHelpers
end
end
module Actiondispatch
class IntegrationTest
include Devise::Test::IntegrationHelpers
end
end
- 这是
app/controllers/application_contoller.rb
文件:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
end
错误
运行命令 bundle exec rspec
后,出现以下错误:
1) ProjectsController create calls the workflow with parameters
Failure/Error:
expect(CreatesProject).to have_received(:new)
.with({name: "Runway",task_string: "start something:2"})
(CreatesProject (class)).new({:name=>"Runway",:task_string=>"start something:2"})
expected: 1 time with arguments: ({:name=>"Runway",:task_string=>"start something:2"})
received: 0 times
# ./spec/controllers/projects_controller_spec.rb:11:in `block (3 levels) in <top (required)>'
谁能帮我解决这个问题?
解决方法
当您添加身份验证代码时,这意味着现在您的所有控件都需要用户登录。请确保您拥有 spec/support/devise.rb
文件,其中包含以下内容
RSpec.configure do |config|
config.include Devise::Test::ControllerHelpers,type: :controller
config.include Devise::Test::ControllerHelpers,type: :view
config.include Devise::Test::IntegrationHelpers,type: :system
config.include Devise::Test::IntegrationHelpers,type: :request
end
现在在您的测试用例中添加两行,一行用于创建 user
,另一行用于登录用户,现在您完成测试 spec/controllers/projects_controller_spec.rb
将具有以下内容
require 'rails_helper'
RSpec.describe ProjectsController,type: :controller do
describe 'create' do
let(:user) { User.create(email: 'test@example.com',password: 'password') }
it 'calls the workflow with parameters' do
sign_in(user)
workflow = instance_spy(CreatesProject,success?: true)
allow(CreatesProject).to receive(:new).and_return(workflow)
post :create,params: { project: { name: "Runway",tasks: "start something:2" } }
expect(CreatesProject).to have_received(:new)
.with(name: 'Runway',task_string: 'start something:2')
end
end
end
注意:第 13 章:安全性测试解释了关于此的所有内容,即使它通过将项目与角色和用户绑定来更进一步,因此您应该阅读两遍以了解所有这些以及为什么它会给出您的错误,随着您的深入需要为角色和工作流程添加更多更改。