TIL - 2021.05.21 (Fri)

Youngwoo Lee·2021년 6월 26일
0

TIL

목록 보기
26/29
post-thumbnail

TIL Notion -> Velog 하면서 복습하기

Unit Testing URLSession using URLProtocol

참고자료
How to mock URLSession using URLProtocol.
Apple Developer Documentation
Mock URLProtocol for local unit testing


URLProtocol

우리가 request를 생성할 때, 시스템은 내부적으로 request를 처리할 수 있는 등록된 프로토콜 클래스를 확인하고, request를 찾으면 해당 클래스에 네트워크 작업을 완료할 책임을 부여합니다. 이 방법을 통해 네트워크 계층을 가로챌 수 있으며, URL 프로토콜을 확장하여 모의 클래스를 만들고 아래와 같이 장치 테스트 사례를 작성하는 데 도움이 되는 모든 필요한 방법을 재정의하기만 하면 됩니다.

  • client : The object the protocol uses to communicate with the URL loading system.

  • startLoading() : Starts protocol-specific loading of the request

    When this method is called, the subclass implementation should start loading the request, providing feedback to the URL loading system via the URLProtocolClient protocol.

    Subclasses must implement this method.

  • stopLoading() : Stops protocol-specific loading of the request

    When this method is called, the subclass implementation should stop loading a request. This could be in response to a cancel operation, so protocol implementations must be able to handle this call while a load is in progress. When your protocol receives a call to this method, it should also stop sending notifications to the client.

    Subclasses must implement this method.

  • canonicalRequest(for request: URLRequest) → URLRequest

    Returns a canonical version of the specified request ( 특정 요청의 표준 버전을 반환한다 )

  • canInint(with: URLRequest) → Bool

    Determines whether the protocol subclass can handle the specified request

    특정 요청을 프로토콜의 서브클래스가 결정할지 안할지?

class MockURLProtocol: URLProtocol {
	static var requestHandler: ((URLRequest) -> (HTTPURLResponse?, Data?, Error?))?

	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 handler = MockURLProtocol.requestHandler else {
			return
		}
		
		let (response, data, error) = handler(request)

		if let error = error {
			client?.urlProtocol(self, didFailwithError: error)
		}

		if let response = response {
			client?.urlProtocol(self, didReceive: response, cachesStoragePolicy: .notAllowed)
		}

		if let data = data {
			client?.urlProtocol(self, didLoad: data)
		}

		client?.urlProtocolDidFinishLoading(self)
	}

	override func stopLoading() {
		
	}
}

쉽게 생각해서 URLSession의 dataTask 내의 동작을 Custom으로 설정하는 과정이다

원래 같으면 웹 서버에서 데이터를 불러오는 과정이겠지만,

우리가 지정하게 된다면 마음대로 data와 response를 바꿔줄 수 있다

위 방법을 이용해서 서버, 네트워크에 의존하지 않는 URLSession Test를 할 수 있을 것 같다

profile
iOS Developer Student

0개의 댓글