XCTestCase 在 Swift 中使用 URLProtocolStub 与 Alamofire 进行多部分参数

问题描述 投票:0回答:1

我想知道如何使用 Alamofire(网络堆栈)测试多部分发送参数。例如:发送带有图像的字符串(数据类型)。

我的问题是,当我收到响应时,我收到 URLRequest 并检查 httpBody 以获取我的参数。不幸的是它是零,我不知道另一种获取 multipartData 的方法。

(在这里提问之前我已经做了一些搜索;))

为此,我创建了一个存根 URLProtocol(称为 URLProtocolStub)

final class URLProtocolStub: URLProtocol {
    private struct Stub {
        let data: Data?
        let response: URLResponse?
        let error: Error?
        let requestObserver: ((URLRequest) -> Void)?
    }
    
    private static var _stub: Stub?
    private static var stub: Stub? {
        get { return queue.sync { _stub } }
        set { queue.sync { _stub = newValue } }
    }
    
    private static let queue = DispatchQueue(label: "URLProtocolStub.queue")
    
    static func stub(data: Data?, response: URLResponse?, error: Error?) {
        stub = Stub(data: data, response: response, error: error, requestObserver: nil)
    }
    
    static func observeRequests(observer: @escaping (URLRequest) -> Void) {
        stub = Stub(data: nil, response: nil, error: nil, requestObserver: observer)
    }
    
    override class func canInit(with request: URLRequest) -> Bool {
        return true
    }
    
    override class func canonicalRequest(for request: URLRequest) -> URLRequest {
        return request
    }
    
    override func startLoading() {
        guard let stub = URLProtocolStub.stub else { return }
        
        if let data = stub.data {
            client?.urlProtocol(self, didLoad: data)
        }
        
        if let response = stub.response {
            client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
        }
        
        if let error = stub.error {
            client?.urlProtocol(self, didFailWithError: error)
        } else {
            client?.urlProtocolDidFinishLoading(self)
        }
        
        stub.requestObserver?(request)
    }
}

我将其设置在 URLConfigurationSession 上,以便在 Alamaofire 上使用虚假会话。

let configuration = URLSessionConfiguration.af.ephemeral
configuration.protocolClasses = [URLProtocolStub.self] 

最后,我的测试函数用于使用多部分数据测试 HTTP 请求。

func test_uploadMultipart_with_params() async {
        // 1
        let httpURL = HTTPURLResponse(statusCode: 204)
        let bodyParams = ["firstname": "mock", "lastname": "test"]
        let imageData = UIColor.yellow.image(CGSize(width: 128, height: 128)).jpegData(compressionQuality: 0.7)

        URLProtocolStub.stub(data: nil, response: httpURL, error: nil)

        let exp = expectation(description: "Waiting to receive response")

        // 2
        let loggerDelegate = StubHTTPLoggerDelegate(didReceivedResponse: { request in
            XCTAssertEqual(request?.httpBody.flatMap { String(data: $0, encoding: .utf8) }, "firstname=mock&lastname=test")
            exp.fulfill()
        })

        // 3
        let result = await makeSUT(loggerDelegate: loggerDelegate).requestMultipart(imageDatas: [imageData], pathType: anyPathType(.post, bodyParameters: bodyParams, urlParameters: nil))

        do { try result.get() } catch { XCTFail("\(error)") }

        wait(for: [exp], timeout: 1.0)
    }

我一步步解释这个功能:

  1. 我为我的多部分请求准备了我的 bodyParams 和图像。
  2. 我创建一个侦听器来侦听收到的 HTTP 响应。
  3. 我通过传递侦听器创建我的 AlamofireHTTPClient(makeSUT 函数),并使用我的 bodyParams 和图像调用我的 Alamorefire requestMultipart。然后执行我的客户端。

我的测试是检查我是否在 Alamofire 多部分请求上发送正确的参数。 此测试失败,因为请求 (URLRequest) 中的 httpBody 为零,并且我不知道如何获取我的多部分参数来测试它:(。

谢谢你帮助我:)。

ios swift alamofire xctest
1个回答
0
投票

在多种形式的零件数据中,主体或多或少是一个大数据,可以分为多个子数据(如果我们“拆分它们”:

Data1+Data2+Data3...+DataN
):

Data1 //Boundary
Data2 //SomeParam1
Data3 //Boundary
Data4 //SomeParam2
Data5 //Boundary
...

现在,NOT任何

Data
值都可以转换为UTF8字符串。某些“位组合”没有 UTF8 值,因此您可以获得可能为零的
String(data: someData, encoding: .utf8)
。 你可以自己尝试一下,因为你有图像:
print("Image to Str: \(String(data: imageData, encoding: .utf8))")
,那就是
nil

因此,如果您尝试将大数据转换为字符串,它将无法工作,因为中间的某些部分是图像,并且为零。

所以实际上,你应该分裂你的身体并收回每个部分。 边界应该位于标题中,因此您应该能够检索它。 ,通常也有很多“ “ 和 ” ”和“-”作为分隔符。 然后,你必须迭代并找到所需的值。

© www.soinside.com 2019 - 2024. All rights reserved.