问题描述
我对 Vapor 中的 http/html(不是 JSON)服务器进行了一系列测试。在 Users db 中创建一个用户,然后使用 POST 请求登录,以确认该用户存在,并得到肯定的响应:
2021-06-17T13:17:43+0700 info codes.vapor.request : request-id=97BBFF64-52B8-4988-BA79-236A43C0212F POST /test/login/
logged in stressed_tangerine_hedgehog@sillyname.org
如果我使用正在运行的服务器手动做同样的事情,在开发数据库上,我得到了同样的肯定结果,cookie就在那里:(使用迅雷客户端):
如果我然后到达测试端点,一个简单的 get 指示是否有会话用户,也使用 ThunderClient,该用户存在。
但是,在测试环境中,当我跟随登录请求到同一端点时,我没有用户:
2021-06-17T13:17:43+0700 info codes.vapor.request : request-id=5D8FA5FC-B176-4355-9A37-FAE01772A1C6 GET /test/
not logged in
测试端点如下所示:
func getTestHandler(req: Request) -> String {
guard let user = req.auth.get(User.self) else {
print("not logged in")
return "not logged in"
}
print(user.username)
return "got the handler"
}
...并且返回的消息在迅雷客户端中是正确的。
Vapor 测试环境中的 XCTAssert 测试是否没有实现任何形式的会话 cookie,如果没有,是否有解决方法?如果是这样,我该怎么做才能让它们工作?
解决方法
您有责任捕获登录响应中设置的 cookie 并将其与测试中的后续请求一起发送
,第一个方法是在测试中需要访问登录路由时调用的方法。 loggedInUser
和 passwordToLoginWith
是将要进行身份验证的用户。 body
提供您最终调用所需的上下文。 loginPath
中的 setLoginCookie
是您的身份验证端点。其余的应该是不言自明的。
extension UserTests {
func getResponse<T: Content>(to path: String,method: HTTPMethod = .POST,body: T,loggedInUser: User? = nil,passwordToLoginWith: String? = nil,headers: HTTPHeaders = .init()) throws -> Response {
let request = try setupRequest(to: path,method: method,loggedInUser: loggedInUser,passwordToLoginWith: passwordToLoginWith,headers: headers)
try request.content.encode(body)
return try getResponse(to: request)
}
func getResponse(to path: String,method: HTTPMethod = .GET,headers: HTTPHeaders = .init(),loggedInUser: User? = nil) throws -> Response {
let request = try setupRequest(to: path,passwordToLoginWith: stdPass,headers: headers)
return try getResponse(to: request)
}
func setupRequest(to path: String,headers: HTTPHeaders = .init()) throws -> Request {
let request = Request(application: app,url: URI(path: path),headers: headers,on:app.eventLoopGroup.next())
request.cookies["vapor-session"] = try setLoginCookie(for: loggedInUser,password: passwordToLoginWith)
return request
}
func setLoginCookie(for user: User?,password: String? = nil) throws -> HTTPCookies.Value? {
if let user = user {
let loginData = TestController.LoginContext(username: user.username,password: password!,email: user.username)
let loginPath = "/test/login"
let loginResponse = try getResponse(to: loginPath,method: .POST,body: loginData)
let sessionCookie = loginResponse.cookies["vapor-session"]
return sessionCookie
} else {
return nil
}
}
func getResponse(to request: Request) throws -> Response {
return try app.responder.respond(to: request).wait()
}
}
这或多或少是在 Github 项目中找到的,链接由 0xTim 提供。这真的很有用(直到它消失在 Vapor Discord 服务器的流程中;由于社区问题和答案消失在 Discord 的黑喉中的短暂方式,Vapor 社区损失了很多。)