如何解决测试非公共路线会导致KeyError
我是Crystal和Amber的新手,并且在测试非公共路线时遇到问题。我使用了Amber身份验证生成器,然后为Job实体生成了一个支架,并将相关的路由添加到route:auth块。 当我打开浏览器并尝试直接进入工作路线时,所有操作均按预期进行,并且重定向到登录页面。
但是当我为JobsController执行生成的测试时,出现以下错误:
1) JobControllerTest renders job index template
Missing hash key: :auth (KeyError)
from ../../.asdf/installs/crystal/0.35.1/src/hash.cr:1030:9 in ‘[]’
from lib/Amber/src/Amber/pipes/pipeline.cr:19:15 in ‘call’
from lib/garnet_spec/src/garnet_spec/controller/test.cr:25:7 in ‘process_request’
from spec/controllers/job_controller_spec.cr:20:1 in ‘get’
from spec/controllers/job_controller_spec.cr:39:5 in ‘->’
from ../../.asdf/installs/crystal/0.35.1/src/primitives.cr:255:3 in ‘internal_run’
from ../../.asdf/installs/crystal/0.35.1/src/spec/example.cr:33:16 in ‘run’
from ../../.asdf/installs/crystal/0.35.1/src/spec/context.cr:18:23 in ‘internal_run’
from ../../.asdf/installs/crystal/0.35.1/src/spec/context.cr:330:7 in ‘run’
from ../../.asdf/installs/crystal/0.35.1/src/spec/context.cr:18:23 in ‘internal_run’
from ../../.asdf/installs/crystal/0.35.1/src/spec/context.cr:147:7 in ‘run’
from ../../.asdf/installs/crystal/0.35.1/src/spec/dsl.cr:270:7 in ‘->’
from ../../.asdf/installs/crystal/0.35.1/src/primitives.cr:255:3 in ‘run’
from ../../.asdf/installs/crystal/0.35.1/src/crystal/main.cr:45:14 in ‘main’
from ../../.asdf/installs/crystal/0.35.1/src/crystal/main.cr:114:3 in ‘main’
routes.cr
routes :auth do
...
resources "jobs",JobController
end
JobControllerTest.cr
...
class JobControllerTest < GarnetSpec::Controller::Test
getter handler : Amber::Pipe::Pipeline
def initialize
@handler = Amber::Pipe::Pipeline.new
@handler.build :web do
plug Amber::Pipe::Error.new
plug Amber::Pipe::Session.new
plug Amber::Pipe::Flash.new
end
@handler.prepare_pipelines
end
end
describe JobControllerTest do
subject = JobControllerTest.new
it “renders job index template” do
Job.clear
response = subject.get “/jobs” # -> line 39 where the error happens
response.status_code.should eq(302)
response.body.should contain(“jobs”)
end
end
...
我没有在Ambers文档中找到任何信息,也没有在Google上找到任何信息。我的问题如下:
解决方法
您需要在初始化函数中包含auth处理程序吗?
@handler.build :auth do
plug Authenticate.new
end
[更新] 添加了用于添加登录测试的指针。
要测试已验证的路由,可以使用https://docs.amberframework.org/amber/guides/testing/system-tests
中记录的系统测试我没有太多关于进行系统测试的可用API调用的文档。但是从这段代码中,我了解到页面加载后,您可以填写登录名和密码并模拟click事件。 https://github.com/amberframework/garnet-spec/blob/master/src/garnet_spec/system_test.cr
fill(:class_name,"login","test_username")
fill(:class_name,"password","test_pass")
click(:class_name,"login-button")
我尚未测试代码,请根据可用文档在此处更新注释。
,对于您的第二个问题,如果您使用 Amber 附带的基本身份验证,我将以下内容添加到我的 spec_helper.cr
中,并且能够通过从类继承来对经过身份验证的用户进行控制器测试。它确实需要 crystagiri
分片,以便您能够获得 csrf_token。
require "../spec_helper"
require "crystagiri"
def login_params(csrf_token)
params = [] of String
params << "email=admin@example.com"
params << "password=password"
params << "_csrf=#{csrf_token}"
params.join("&")
end
def create_user
user = User.new(email: "admin@example.com",first_name:"Test",last_name:"User")
user.password = "password"
user.save
user
end
def get_csrf_token(response_body)
html = Crystagiri::HTML.new response_body
csrf_token = String.new
html.where_tag("input") do |back|
csrf_token = back.node.attributes[2].content
break
end
csrf_token
end
class ApplicationControllerTest < GarnetSpec::Controller::Test
getter handler : Amber::Pipe::Pipeline
getter current_user = User.new
getter csrf_token = String.new
setter current_user
def initialize
@handler = Amber::Pipe::Pipeline.new
@handler.build :web do
plug Citrine::I18n::Handler.new
plug Amber::Pipe::Error.new
plug Amber::Pipe::Logger.new
plug Amber::Pipe::Session.new
plug Amber::Pipe::Flash.new
plug Amber::Pipe::CSRF.new
plug CurrentUser.new
end
@handler.build :auth do
plug Citrine::I18n::Handler.new
plug Amber::Pipe::Error.new
plug Amber::Pipe::Logger.new
plug Amber::Pipe::Session.new
plug Amber::Pipe::Flash.new
plug Amber::Pipe::CSRF.new
plug CurrentUser.new
plug Authenticate.new
end
@handler.prepare_pipelines
@current_user = create_user
end
def login_user
response = get "/signin"
@csrf_token = get_csrf_token(response.body)
post "/session",body: login_params(csrf_token),headers: HTTP::Headers{"Cookie" => response.headers["Set-Cookie"]}
end
end
然后在您的 class_controller_spec.cr
中,当您在发出请求之前需要用户登录时,您将拥有如下内容
class AccountControllerTest < ApplicationControllerTest
end
describe AccountControllerTest do
subject = AccountControllerTest.new
it "renders account index template" do
subject.current_user = create_user
response_headers = subject.login_user.headers
response = subject.get "/accounts",headers: HTTP::Headers{"Cookie" => response_headers["Set-Cookie"]}
response.status_code.should eq(200)
response.body.should contain("accounts")
end
end
如果您仍在寻找解决方案,希望对您有所帮助!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。