네트워크와 무관한 URLSession Unit Test를 하는 목적

Brad·2022년 7월 23일
0

유닛 테스트란??

유닛 테스트는 컴퓨터 프로그래밍에서 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차. 즉, 모든 함수와 메소드에 대한 테스트 케이스(Test case)를 작성하는 절차를 말함

unit test 는 작성한 프로그램이 의도한 대로 동작하는지 검증하는 가장 작은 단위의 테스트

이를 통해서 각 모듈(클래스, 메소드)들이 잘 동작하는지 확인할 수 있음.

왜 필요할까??

굉장히 비효율적이지 않나.?

유닛 테스트를 하는 이유

  1. 각각의 모듈을 부분적으로 확인할 수 있어 어떤 모듈에서 문제가 발생하는지 빠른 확인이 가능
  2. 전체 프로그램을 빌드하는 대신 유닛 단위로 빌드해 확인하므로 시간 절약

어떻게 작성하는가??

각 테스트 케이스는 서로 분리되어야 하므로(isolated), 가짜 객체 mock object(Stub)를 만들어 테스트 하는 것이 좋다

의존성 주입이 핵심

의존성 주입이란??

의존성

함수에 필요한 클래스나 참조 변수에 의존하는 것을 의미

네트워크와 무관한 URLSession Unit Test를 하는 목적

  • 인터넷에 의존하기 떄문에 테스트를 신뢰할 수 없어서
  • 실제 서버와 통신하면 의도치 않은 결과 도출될 수 있음.. 실제 서버에 영향이 갈 수 도 있다.

URLSession의 Unit Test 포인트

→ URLSession의 Unit Test의 포인튼는 dataTask 작업을 가로채는 것!!

🤔왜? dataTask 작업을 가로챌까??
dataTask는 NSData 객체들을 이용해 특정 URL로부터 정보를 주고 받기 위해 사용 으로 정의되어 있는데 앞서 URLSession의 Unit Test는 실제로 인터넷(서버)와 통신을 하지 않기 떄문에 가짜? API를 만들어야 함.. 그래서 dataTask의 목적지를 가짜로 우회?? 한다고 생각하면 될 것 같다..

구현 전 URLSession의 동작을 생각해보자

  1. URLSession 호출
  2. dataTask 메서드의 호출 및 동작
  3. dataTask 메서드의 종료 및 escaping 클로저를 통한 결과값 반환

→ 네트워크와 무관한 테스트를 위해선 URLSession의 동작 전부를 Mock로 가로채야 한다…

목표

MockURLSession을 만들어서 URLSessionProvider의 응답을 조작하는것..

주목해야 되는 부분

위의 포인트 내용에서 dataTask 작업을 가로채는 것!! 을 강조 한 부분 기본 URLSession 동작을 하는 class를 만드는 dataTask 메소드를 통해 session의 dataTask 메소드를 호출해 사용한다..!

URLSession의 네트워크 동작이 어떻게 동작하던 dataTask를 선언한 메소드의 데이터 흐름을 제어한다면 언제든지 네트워크와 무관한 모델 테스트가 가능해진다..!

🤔 그러면 어떻게 흐름을 제어할까??

URLSession에 존재하는 .dataTask(with: …) 메소드를 새롭게 정의해야 한다.

  • 어디서?
    새롭게 만들 MockURLSession에서..
  • 어떻게?
    URLSessionProtocol을 이용해서
  • 왜??
    dataTask 메소드의 요청에 따른 응답을 우리의 Mock Data로 교체하기 위해서

1. 교체해줄 프로토콜 만들기

프로토콜을 만드는 목적은 진짜 URLSession의 dataTask 메소드를 교체하기 위해서.. 실제 코드에 적용하려면 URLSessionProvider의 let session: URLSession을 우리가 만든 어떤것으로 교체해야함

→ URLSession인 척 하면서 우리가 만든 dataTask 메소드를 가진 가짜를 만들어야 함

새롭게 만든 프로토콜은 dataTask를 구현해야 한다.. 그러고 나서 URLSession의 session에 프로토콜을 채택 시킴으로써 가짜를 호출시키지만 진짜를 호출한 것처럼 정상적으로 돌아가게 된다.!

  • dataTask의 목적지를 바꿔주는 부분이지 않을까 생각된다..
  • 그럼 새로 만든 프로토콜은 어떻게 URLSession 타입을 가질 수 있는ㄱ ㅓ지??
  • extension URLSession: URLSessionSwichingProtol 을 썻기 떄문에??
    확장되어서?! 그렇게되면 URLSessionSwichingProtocol안에 URLSession이 있는 것으로 이해하면 될라나?

URLSessionDataTask???
다운로드한 데이터의 메모리를 앱으로 직접 반환하는 URL 세션 작업

🤔 해주는 이유가 멀까??

resume() 메소드를 override 하는 이유는 기본 URLSession 클래스에서 dataTask가 끝나고 네트워크 통신을 종료하기 위해 resume() 메소드를 호출하고 있는데 대체한 session을 가진 기본 URLSession 클래스는 실제 통신을 하지 않았기 떄문에 resume() 통신 종료 메소드는 무언가 어색함..

그래서 이 메소드가 호출할 떄 클로저가 실행되도록 새롭게 정의한 것.. 그리고 우리는 resume()이 호출되는 시점을 통신의 종료 = 응답 의 시점으로 보고 조작한 응답값을 comletionHandler를 통해 전달함

간단히 요약하자면 dataTask의 모든 동작을 Mock로 대체하기 위해 과정 중 포함되어 있는 URLSessionDataTask도 Mock으로 대체한 것

profile
iOS 개발자가 되고 싶은 브래드 입니다.

0개의 댓글