我想知道如何使用 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)
}
我一步步解释这个功能:
我的测试是检查我是否在 Alamofire 多部分请求上发送正确的参数。 此测试失败,因为请求 (URLRequest) 中的 httpBody 为零,并且我不知道如何获取我的多部分参数来测试它:(。
谢谢你帮助我:)。
在多种形式的零件数据中,主体或多或少是一个大数据,可以分为多个子数据(如果我们“拆分它们”:
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
。
因此,如果您尝试将大数据转换为字符串,它将无法工作,因为中间的某些部分是图像,并且为零。
所以实际上,你应该分裂你的身体并收回每个部分。 边界应该位于标题中,因此您应该能够检索它。 ,通常也有很多“ “ 和 ” ”和“-”作为分隔符。 然后,你必须迭代并找到所需的值。