유닛 테스트는 컴퓨터 프로그래밍에서 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차. 즉, 모든 함수와 메소드에 대한 테스트 케이스(Test case)를 작성하는 절차를 말함
unit test 는 작성한 프로그램이 의도한 대로 동작하는지 검증하는 가장 작은 단위의 테스트
이를 통해서 각 모듈(클래스, 메소드)들이 잘 동작하는지 확인할 수 있음.
굉장히 비효율적이지 않나.?
유닛 테스트를 하는 이유
각 테스트 케이스는 서로 분리되어야 하므로(isolated), 가짜 객체 mock object(Stub)를 만들어 테스트 하는 것이 좋다
즉 의존성 주입이 핵심
함수에 필요한 클래스나 참조 변수에 의존하는 것을 의미
→ URLSession의 Unit Test의 포인튼는 dataTask 작업을 가로채는 것!!
🤔왜? dataTask 작업을 가로챌까??
dataTask는NSData 객체들을 이용해 특정 URL로부터 정보를 주고 받기 위해 사용
으로 정의되어 있는데 앞서 URLSession의 Unit Test는 실제로 인터넷(서버)와 통신을 하지 않기 떄문에 가짜? API를 만들어야 함.. 그래서 dataTask의 목적지를 가짜로 우회?? 한다고 생각하면 될 것 같다..
→ 네트워크와 무관한 테스트를 위해선 URLSession의 동작 전부를 Mock로 가로채야 한다…
MockURLSession을 만들어서 URLSessionProvider의 응답을 조작하는것..
위의 포인트 내용에서 dataTask 작업을 가로채는 것!! 을 강조 한 부분 기본 URLSession 동작을 하는 class를 만드는 dataTask 메소드를 통해 session의 dataTask 메소드를 호출해 사용한다..!
URLSession의 네트워크 동작이 어떻게 동작하던 dataTask를 선언한 메소드의 데이터 흐름을 제어한다면 언제든지 네트워크와 무관한 모델 테스트가 가능해진다..!
🤔 그러면 어떻게 흐름을 제어할까??
URLSession에 존재하는 .dataTask(with: …) 메소드를 새롭게 정의해야 한다.
프로토콜을 만드는 목적은 진짜 URLSession의 dataTask 메소드를 교체하기 위해서.. 실제 코드에 적용하려면 URLSessionProvider의 let session: URLSession을 우리가 만든 어떤것으로 교체해야함
→ URLSession인 척 하면서 우리가 만든 dataTask 메소드를 가진 가짜를 만들어야 함
새롭게 만든 프로토콜은 dataTask를 구현해야 한다.. 그러고 나서 URLSession의 session에 프로토콜을 채택 시킴으로써 가짜를 호출시키지만 진짜를 호출한 것처럼 정상적으로 돌아가게 된다.!
URLSessionDataTask???
다운로드한 데이터의 메모리를 앱으로 직접 반환하는 URL 세션 작업
🤔 해주는 이유가 멀까??
resume() 메소드를 override 하는 이유는 기본 URLSession 클래스에서 dataTask가 끝나고 네트워크 통신을 종료하기 위해 resume() 메소드를 호출하고 있는데 대체한 session을 가진 기본 URLSession 클래스는 실제 통신을 하지 않았기 떄문에 resume() 통신 종료 메소드는 무언가 어색함..
그래서 이 메소드가 호출할 떄 클로저가 실행되도록 새롭게 정의한 것.. 그리고 우리는 resume()이 호출되는 시점을 통신의 종료 = 응답 의 시점으로 보고 조작한 응답값을 comletionHandler를 통해 전달함
간단히 요약하자면 dataTask의 모든 동작을 Mock로 대체하기 위해 과정 중 포함되어 있는 URLSessionDataTask도 Mock으로 대체한 것