gpt4 book ai didi

XCTestCase Multipart params with Alamofire using URLProtocolStub in Swift(在SWIFT中使用URLProtocolStub通过AlamoFire实现多部分参数XCTestCase)

转载 作者:bug小助手 更新时间:2023-10-25 17:29:31 24 4
gpt4 key购买 nike



I would like to know how can I test multipart sending params with Alamofire (network stack). Ex: send a string with an image (Data type).

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


My issue is that when I receive a response, I get the URLRequest and I check the httpBody for getting my params. Unfortunately it is nil and I don’t know another way to get multipartData.

我的问题是,当我收到响应时,我会收到URLRequest,并检查http Body以获取我的Pars。不幸的是,它是空的,我不知道另一种获取多部分数据的方法。


(I’ve already do some search before asking here ;))

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


For Doing this, I create a stub URLProtocol (called URLProtocolStub)

为此,我创建了一个存根URL协议(名为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)
}
}

And I set it on the URLConfigurationSession for use a fake session on Alamaofire.

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


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

Finally, my test function for testing HTTP request with multipart data.

最后,我的测试函数用于测试包含多部分数据的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)
}

I explain this function step by step :

我将一步一步地解释此功能:



  1. I prepare my bodyParams & image for my multipart request.

  2. I create a listener for listen HTTP response when received.

  3. And I create my AlamofireHTTPClient (makeSUT function) by passing my listener and call my Alamorefire requestMultipart with my bodyParams & image. Then a execute my client.


My test is checking if I am sending the right parameters on a Alamofire multipart request.
This test failed because the httpBody from a request (URLRequest) is nil and I don't know how to get my multipart params to test it :(.

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


Thanks for helping me :).

谢谢你帮我:)。


更多回答
优秀答案推荐

Without seeing the underlying Alamofire call I can't be sure but Alamofire's multipart uploads use a URLSessionUploadTask from a file or memory, so the URLRequest that is performed will have no httpBody. Instead, it uses the httpBodyStream to stream the data from disk or memory, so you'll need to read that data to do your parsing and comparisons, taking into account the issues @Larme mentioned.

如果没有看到底层的Alamofire调用,我不能确定,但Alamofire的多部分上传使用了来自文件或内存的URLSessionUploadTask,因此执行的URLRequest将不会有httpBody。相反,它使用httpBodyStream从磁盘或内存中传输数据,因此您需要读取该数据来进行解析和比较,同时考虑到@Larme提到的问题。



In multiform part data, the body is more or less a big data that can be separated into multiple subdata (that if we "split them": Data1+Data2+Data3...+DataN):

在多形式部件数据中,正文或多或少是一个可以分成多个子数据的大数据(如果我们将它们拆分:data1+data2+data3...+datan):


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

Now, NOT any Data value can be converted into UTF8 String. Some "bits combinaison" don't have UTF8 value, hence why you can get String(data: someData, encoding: .utf8) that can be nil.
And you can try it yourself since you have an image:
print("Image to Str: \(String(data: imageData, encoding: .utf8))") and it would be nil.

现在,不是任何数据值都可以转换为UTF8字符串。有些“位组合”没有UTF8值,因此您可以得到可以为空的字符串(data:ome Data,Coding:.utf8)。而且您可以自己尝试,因为您有一个图像:Print(“Image to Str:\(String(data:ImageData,Coding:.utf8))”),它将是空的。


So if you are trying to convert your big data into a String, it won't work since some part in the middle is the image and will be nil.

因此,如果您试图将大数据转换为字符串,这将不起作用,因为中间的某个部分是图像,将为零。


So in reality, you should split your body and retrieve each part.
The boundary should be in the Header so you should be able to retrieve it. , There are also usually a lot of "\n" and "\r" and "-" as separators.
Then, you have to iterate and find the desired value.

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


更多回答

To continue on the first point, user can test it by removing the XCTAssertEqual(request?.httpBody.flatMap...) and expectation and print the content of httpBoyd instead with the help of stackoverflow.com/questions/39075043/…

要继续第一个点,用户可以通过删除XCTAssertEquity(REQUEST?.HTTPBody.flatMap...)来测试它并期望并借助stackoverflow.com/Questions/39075043/…打印HTTPBoyd的内容

@JonShier I received also nil on httpBodyStream

@JonShier我在HTTPBodyStream上也收到了nil

@TharsanE. to see the httpBodyStream that's added, you need to observe the task.currentRequest. That should be updated when URLSession adds the stream. See stackoverflow.com/a/77197538/272952

@TharsanE.要查看添加的httpBodyStream,您需要观察task.CurrentRequest.它应该在URLSession添加流时更新。参见Stackoverflow.com/a/77197538/272952

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com