XCTest 中未保留经过身份验证的 Vapor 会话

Posted

技术标签:

【中文标题】XCTest 中未保留经过身份验证的 Vapor 会话【英文标题】:Authenticated Vapor session not preserved inside an XCTest 【发布时间】:2020-05-29 10:43:44 【问题描述】:

应用程序本身运行良好,但我无法进行确认这一点的测试。

在下面的第 1 部分中,测试检查使用电子邮件和(正确的)密码登录是否成功,并返回正确的 URL 重定向。在重定向返回测试之前的代码中,调试显示对request.auth.require(User.self) 的调用成功。

在第 2a 部分和第 2b 部分中,XCTAssertEqual 失败,并且日志显示调用 request.auth.require(User.self) 的结果引发了错误,提示用户未获得授权。

第 3 部分再次检查第 1 部分是否正常工作,因为它也为不成功的登录返回正确的 URL 重定向。

因此,似乎会话数据在调用.test(...) 之后没有被保留。有没有办法解决这个问题?

@testable import App
import XCTVapor
final class AppTests: XCTestCase

    func test011UserLoginLogout() throws
    
        func attemptLogin(withPassword password:String, completion:(XCTHTTPResponse) throws -> ()) throws -> Void
        
            var body = ByteBufferAllocator().buffer(capacity: 0)
            body.writeString(#""email":"me@example.com","password":"\#(password)""#)
            var headers = HTTPHeaders()
            headers.replaceOrAdd(name: .contentLength, value: body.readableBytes.description)
            headers.contentType = .json
            try app.test(.POST, "/login", headers:headers, body:body)  response in try completion( response ) 
        

        var app = Application(.testing)
        app.databases.use(.mysql(hostname:DBHost, username:DBAccount, password:DBPassword, database:DBDatabase, tlsConfiguration:.none), as:.mysql)
        app.databases.default(to:.mysql)
        do  try configure(app!) 
        catch  XCTFail("configure(app) failed") 
        //  Part 1 succeeds
        try attemptLogin(withPassword:"goodPassword")
        
            res in
            XCTAssertEqual(res.status, HTTPResponseStatus.seeOther)
            XCTAssertEqual(res.headers["location"].first,"success")
            try app!.test(.GET, "/success")
            
                response in
                XCTAssertEqual(response.status, .ok) // <--- Part 2(a) fails
            
        

        try app.test(.GET, "/success")
        
            response in
            XCTAssertEqual(response.status, .ok) // <-- Part 2(b) fails
        

        // Part 3 succeeds
        try attemptLogin(withPassword:"badPassword")
        
            response in
            XCTAssertEqual(response.status, .seeOther)
            XCTAssertEqual(response.headers["location"].first,"failed")
        
    

【问题讨论】:

【参考方案1】:

我认为您在失败的请求中缺少身份验证。如果使用会话,则需要将会话 cookie 传递给失败的请求,如果使用承载身份验证,则需要将令牌传递给失败的请求。

【讨论】:

谢谢,@0xTim。有意思,我去看看。我也许可以从对登录后测试的响应中捕获 cookie,然后手动传递它。 一路走来,@0xTim!我现在将会话 cookie 传递到请求标头中,但它仍然失败,因为 XCTHTTPRequest 中没有会话属性。 是的,这就是要走的路,从登录响应中获取登录 cookie(通常在 vapor-session 下,并将其添加到未来的请求中。否则,您尝试发送的请求与未经身份验证的请求。Here's an example 这样做(但不使用 XCTVapor) 切换到不和谐,@OxTim?我可以设置厨师,没问题,但它会使用它来查找会话数据中的 _UserSession 值。

以上是关于XCTest 中未保留经过身份验证的 Vapor 会话的主要内容,如果未能解决你的问题,请参考以下文章

Spring oauth2令牌请求中未实际使用的基本身份验证过滤器和身份验证入口点

在 Firebase 电话身份验证中未接收代码。

XCTest:UI测试类中的NSUserdefaults中未检索到的值

Azure AD 在 .NET Core 3.1 中未进行身份验证

Express Passportjs在路由器回调中未进行身份验证

Alamofire 5中未设置授权标头?