Vapor 4 中的测试如何整合会话?

问题描述

我对 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就在那里:(使用迅雷客户端):

screen shot of Thunder Client

screen shot of Thunder Client

如果我然后到达测试端点,一个简单的 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 并将其与测试中的后续请求一起发送

,

第一个方法是在测试中需要访问登录路由时调用的方法。 loggedInUserpasswordToLoginWith 是将要进行身份验证的用户。 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 社区损失了很多。)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...