API 클라이언트 및 랩퍼의 단위 테스트


14

필자는 개발중인 API 클라이언트 라이브러리를 단위 테스트하는 가장 좋은 방법을 찾으려고 노력했습니다. 라이브러리에는 Client기본적으로 API와의 1 : 1 매핑이있는 Wrapper클래스 와 의 맨 위에보다 사용자에게 친숙한 인터페이스를 제공 하는 추가 클래스가 Client있습니다.

Wrapper --> Client --> External API

내가 먼저 모두에 대해 테스트의 무리를 작성 Client하고 Wrapper효과적으로 단지 그들이 앞으로가에서 작동 어떤의 적절한 기능 (즉, 그 테스트 Wrapper에 대한 운영 ClientClientHTTP를 연결에서 작동). 그러나 인터페이스가 아닌 이러한 클래스의 구현을 테스트하고 있다고 느끼기 때문에 이것에 불편 함을 느끼기 시작했습니다. 이론적으로 클래스를 변경하여 완벽하게 유효한 다른 구현을 할 수는 있지만 호출 될 것으로 예상되는 함수가 호출되지 않아 테스트가 실패합니다. 그것은 나에게 연약한 시험처럼 들린다.

그 후, 나는 수업의 인터페이스에 대해 생각했습니다. 테스트는 클래스가 실제로 수행하는 방식이 아니라 수행하려는 작업을 실제로 수행하는지 확인해야합니다. 어떻게해야합니까? 가장 먼저 떠오르는 것은 외부 API 요청을 스텁하는 것입니다. 그러나 외부 서비스를 지나치게 단순화하는 것에 신경이 쓰입니다. 내가 본 스텁 API의 많은 예제는 미리 준비된 응답을 제공합니다. 이는 가짜 API에 대해 코드가 올바르게 실행되는지 테스트하는 정말 쉬운 방법 인 것 같습니다. 대안은 서비스를 조롱하는 것인데, 이는 실현 불가능하며 실제 서비스가 변경 될 때마다 최신 상태를 유지해야합니다.

마지막으로 프로그래머 SE에 대한 다른 답변에서 이것을 읽었습니다 .

원격 API 클라이언트의 임무는 특정 호출을 발행하는 것입니다. 따라서 테스트를 통해 해당 호출을 발행하는지 확인해야합니다.

그리고 지금 나는 다소 확신합니다-테스트 할 때 테스트 Client해야 할 것은 API에 올바른 요청을한다는 것입니다 (물론 API가 변경 될 가능성은 항상 있지만 테스트는 계속 진행됩니다) 통합 테스트가 유용한 곳). ClientAPI를 사용한 1 : 1 매핑 이기 때문에 하나의 유효한 구현에서 다른 구현으로 변경하기 전의 관심사는 실제로 적용되지 않습니다 Client.의 각 메소드에 대해 하나의 유효한 구현 만 있습니다.

그러나 나는 여전히 Wrapper수업에 갇혀 있습니다. 다음과 같은 옵션이 있습니다.

  1. Client클래스를 스텁 아웃하고 적절한 메소드가 호출되는지 테스트합니다. 이 방법으로 위와 동일한 작업을 수행하지만 ClientAPI의 독립형으로 취급합니다 . 이것은 내가 시작한 곳을 바로 돌려줍니다. 다시 한번, 이것은 인터페이스가 아닌 테스트 구현의 불편한 느낌을줍니다. 은 Wrapper아주 잘 완전히 다른 클라이언트를 사용하여 구현 될 수있다.

  2. 나는 모형을 만듭니다 Client. 이제는 그것을 조롱하는 데 얼마나 멀리 갈지를 결정해야합니다. 서비스의 완전한 모의를 만들려면 많은 노력이 필요합니다 (라이브러리 자체에 들어간 것보다 더 많은 작업). API 자체는 간단하지만 서비스는 상당히 복잡합니다 (기본적으로 해당 데이터에 대한 작업이있는 데이터 저장소입니다). 그리고 다시, 내 목을 실제와 동기화해야합니다 Client.

  3. 적절한 HTTP 요청이 수행되고 있는지 테스트합니다. 즉 , HTTP 요청을하기 위해 Wrapper실제 Client객체를 통해 호출 하므로 실제로 테스트하지는 않습니다. 이것은 약간 끔찍한 단위 테스트입니다.

따라서 나는 이러한 솔루션 중 어느 것에도 만족하지 않습니다. 당신은 무엇을 하시겠습니까? 이것에 대해 올바른 방법이 있습니까?


나는 대부분의 gruntwork을 수행하는 타사 라이브러리가 있고 단지 래퍼 만있는이 시나리오에서 단위 테스트를 피하는 경향이 있습니다 (주로 실제로 의미있는 것을 테스트하는 방식으로이를 수행하는 방법을 모르기 때문에). 일반적으로 가능한 경우 모의 서비스를 사용하여 통합 테스트를 수행합니다. 어쩌면 누군가가 이것에 대해 정말로 의미있는 단위 테스트를 수행하는 방법을 알고있을 것입니다. 저는 우리가 통제하는 시스템에서 가장 중요한 구성 요소를 우선시하는 경향이 있습니다. 여기서 중요한 부분은 우리가 통제 할 수없는 것입니다. :-(

답변:


10

TLDR : 어려움에도 불구하고 서비스를 스텁하고 클라이언트 유닛 테스트에 사용해야합니다.


API가 항상 고정 상태를 반환하고 소비하거나 생성하지 않는 끝점으로 구성되지 않는 한 "원격 API 클라이언트의 작업은 더 이상, 더 이상, 더 이상, 특정 호출을 발행하는 것이 아니라"라고 확신하지 않습니다. 모든 데이터. 이것은 가장 유용한 API가 아닙니다 ...

또한 클라이언트 가 올바른 요청을 보낼 뿐만 아니라 응답 내용, 오류, 리디렉션 등을 올바르게 처리하는지 확인하고 이러한 모든 경우를 테스트해야합니다.

참고로 랩퍼-> 클라이언트-> 서비스-> DB 이상의 전체 스택을 포괄하는 통합 테스트가 있어야하지만 통합 테스트를 모든 부분의 일부로 실행할 수있는 환경이 없다면 주된 질문에 대답해야합니다. 많은 두통 (공유 테스트 데이터베이스 등)없이 CI를 빌드하려면 API 스텁을 만드는 데 시간을 투자해야합니다.

스텁을 사용하면 서비스 자체의 하위 계층을 구현할 필요없이 서비스의 실제 구현을 작성할 수 있습니다.

REST 자원 아래에 리포지토리 패턴을 구현하여 DI 기반 솔루션을 사용하여이를 수행 할 수 있습니다.

  • REST 핸들러의 모든 기능 코드를 IWhateverRepository에 대한 호출로 바꾸십시오.
  • REST 자원에서 추출 된 코드와 단위 테스트 중에 사용하기 위해 미리 준비된 응답을 리턴하는 TestWhateverRespository를 사용하여 ProductionWhateverRepository를 작성하십시오.
  • DI 컨테이너를 사용하여 구성에 따라 ProductionWhateverRepository 또는 TestWhateverRepository DLL / 클래스 등을 주입하십시오.

어쨌든, 서비스를 스터 빙 및 / 또는 리팩토링하는 것이 정치적으로나 실질적으로 문제가 아닌 한, 나는 아마도 위와 비슷한 것을 수행 할 것입니다. 가능하지 않다면, 통합 범위가 정말 우수하고 가능한 테스트 설정이 주어지면 가능한 한 자주 실행하십시오.

HTH

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.