단위 테스트에 의존성 주입이 필수적입니까?


55

사용 의존성 주입 단위 테스트 (DI) 필수을?

코드를 격리하는 또 다른 대안을 생각할 수 없으므로 테스트 할 수 있습니다. 또한 내가 본 모든 예제는이 패턴을 사용합니다. 이것이 유일하게 실행 가능한 옵션이거나 다른 대안이 있습니까?


5
의존성 주입은 필수는 아니지만 제어의 역전 개념이 더 광범위합니다.
Jeremy Heiler

이 스케일에 대해 말할 것이 있습니다. 레이어가 거의없는 작은 코드 기반이 있으면 DI가 유용하지 않을 수 있습니다.
JB King

@JBKing 작은 코드 기반이 있다면 레이어 나 단위 테스트가 필요하지 않습니다
Sklivvz

1
코드를 테스트 할 수있게하려면 많은 디자인 결정이 필요합니다. 테스트 작성을 시작하십시오.
Nathan Cooper

답변:


42

DI는 단위 테스트를 훨씬 쉽게 해줍니다. 그러나 DI 없이도 단위 테스트를 작성할 수 있습니다. DI가 널리 퍼지기 전에 많은 단위 테스트가 이미 작성되었습니다. (물론, 이러한 기술 중 일부는 DI라는 이름과 동일하거나 매우 유사합니다. :-)

DI에 대해 배우기 전에 인터페이스와 팩토리를 많이 사용했습니다. 실제 팩토리 클래스 이름은 구성 파일에서 읽거나 인수로 SUT에 전달되었을 수 있습니다.

다른 방법은 싱글 톤 (또는 일반적으로 전 세계적으로 액세스 가능한 데이터)을 사용하는 것입니다. 그렇습니다. 일반적으로 자신을 포함하여 많은 사람들이 권장하지 않는다는 것을 알고 있습니다. 또 그 수도 싱글 테스트 케이스 특정 아닌 정적 구성 데이터를 포함하지만, 생산 및 시험 환경 다르기 특히, 특정 상황에서 실행 가능. 물론 알려진 문제가 있으므로 사용할 수 있으면 DI가 우수합니다. 그러나 종종 (예를 들어 레거시 시스템에서) 할 수 없습니다.

그중 이야기 레거시 코드와 함께 효과적으로 작동 트릭을 많이 설명하는 것은 테스트에 포함 레거시 코드를 얻을 수 있습니다. 이들 중 많은 부분이 좋지 않고 장기적인 해결책이 아닙니다. 그러나 다른 방법으로는 테스트 할 수없는 시스템에 대한 첫 번째 유용한 단위 테스트를 만들 수 있습니다. 리팩토링을 시작할 수 있으며 결국 DI를 도입 할 수 있습니다.


동의 한 DI는 객체를 조롱하는 데 특히 유용합니다. 그러나 DI가 테스트에서 쓸모없는 시나리오가 많이 있습니다.
Kemoda

예를 들어 @Kemoda 좋아?
BЈовић

@VJovic 예를 들어 독립형 개체입니다. 나는 몇 가지 인수를 취하고 어떤 것을 수행하지만 다른 구성 요소에 의존하지 않는 방법을 생각합니다 (따라서 DI가 필요하지 않음).
Kemoda

@Kemoda 함수형 프로그래밍을 설명하고 있고 DI를 사용하고있는 것 같습니다. 메소드 매개 변수로 종속성을 주입하고 있습니다.
Erik Dietrich

3
@ huggie, 왜 구현 세부 정보가 유출됩니까? 삽입 된 종속성은 일반적으로 인터페이스 뒤에 숨겨져 있으며, 요점은 클라이언트 클래스가이 종속성의 실제 구현이 실제 프로덕션 클래스인지 모의인지 전혀 알지 못하고 염려하지 않는다는 것입니다. 인스턴스화는 클라이언트 클래스 외부에서 발생하며 기성 인스턴스 만 볼 수 있습니다.
Péter Török

56

디커플링 은 단위 테스트에 필수적입니다. DI는 디커플링을 달성하는 좋은 방법입니다.


17
절대로 질문에 대답하지 않는 매우 진실한 진술.
트래비스

10

사용중인 기술에 따라 DI를 사용하지 않고도 종속성을 격리 할 수 ​​있습니다. 예를 들어, .NET 세계에서 Moles를 사용하면 DI 패턴없이 종속성을 격리 할 수 ​​있습니다.

즉, 이러한 격리 프레임 워크는 외부 종속성 (파일 시스템, 데이터베이스 등)이있는 코드의 상황을 위해 작성되었으며 의도 된 것입니다. 즉, 이것을 할 수 있다는 사실이 그 또는 그녀가해야한다는 것을 의미하지는 않습니다.

의존성 주입은 단위 테스트를 허용하지만 해당 객체의 코드를 변경하지 않고도 객체의 동작을 수정할 수 있습니다 (개방 / 폐쇄 원리). 따라서 테스트 가능한 코드 일뿐 아니라 유연한 코드가 생성됩니다. 일반적으로 유지 관리 가능 / 유연한 코드와 테스트 가능한 코드 사이에는 큰 상관 관계가 있음을 발견했습니다.


3
또는 Moles를 사용하면 마술을 통해 테스트하기 때문에 깨끗하고 팩터링 가능한 테스트 가능한 코드가 있다고 생각할 수 있습니다.
Wyatt Barnett

@WyattBarnett 맞아요. Moles는 누군가에게 "이 다형성과 개방 / 폐쇄 물을 모두 필요로합니까?!"
Erik Dietrich

1
두더지는 대체되었다 가짜 와 가짜 페이지에서 "모조품 프레임 워크는 개발자가 단위 테스트에서 더미 구현을 생성, 유지, 및 주입하는 데 도움이"나에게 DI 것 같네요.
서명

1
@Sign 또한 "Fake 프레임 워크를 사용하여 봉인 된 유형의 비가 상 및 정적 방법을 포함한 모든 .NET 방법을 shim 할 수 있습니다"라고 말합니다. 격리 프레임 워크는 DI와 함께 사용할 수 있다는 사실은 그들이 것을 의미하지 않는다 있습니다 DI를.
Erik Dietrich

4

아니요, DI는 단위 테스트에 필수적인 것은 아니지만 많은 도움이됩니다.

DI와 마찬가지로 팩토리 나 로케이터를 사용 하여 테스트 할 수 있습니다 (우아하지 않고 더 많은 설정이 필요함).

또한 모의 객체 는 많은 호출이 종속성 대신 함수에 위임되는 레거시 시스템에서 중요합니다. (모의 객체는 적절한 설정에서도 광범위하게 활용할 수 있습니다)

테스트가 거의 불가능한 설정이있을 수 있습니다. 그러나 이것은 의존성 주입의 사용 여부에 근거하지 않습니다.


3

아니요 , 의존성 주입은 단위 테스트에 필수적이지 않습니다.

의존성 주입은 일부 하위 처리를 수행하기 위해 종속 클래스 인스턴스가 필요한 클래스가있는 경우 도움이됩니다. DI 대신 비즈니스 방법의 논리를 단위 테스트 할 수없는 데이터 연결 부분과 단위 테스트 할 수있는 계산 부분으로 분리 할 수 ​​있습니다.

예 (DI 사용)이 구현은 Employee, Account, ...에 따라 다릅니다.

 bool hasPermissionToTransferMoney(Employee employee, Account from, Account to, Money amount)
 {
     if (amount > 100 && employee.isStudent())
        return false;
     if (to.getOwner().getFamiliyName() == employee.getFamilyName() && ...
        return false; // cannot transfer money to himself;
     ...
 }

데이터 수집 및 계산 분리 후 :

 bool hasPermissionToTransferMoney(Employee employee, Account from, Account to, Money amount)
 {
     return hasPermissionToTransferMoney(employee.isStudent(), employee.getFamilyName(), to.getOwner().getFamilyName(), ...);
 }

 // the actual permission calculation
 static bool hasPermissionToTransferMoney(boolean isStudent, string employeeFamilyName, string receiverFamilyName, ...)
     if (amount > 100 && isStudent)
        return false;
     if (receiverFamilyName == employeeFamiliyName && ...
        return false; // cannot transfer money to himself
     ...
 }

의존성 주입없이 계산 부분을 쉽게 테스트 할 수 있습니다.


1
  • 의존성 주입은 단위 테스트에 필수적이지 않습니다

  • 반면에 한 구현을 다른 구현으로 바꾸고 싶을 때는 제어 역전이 필수적입니다.


0

예, 절연을 위해 DI를 사용하는 것에 대한 대안이 있습니다.

하나의 대안은 실제 객체 대신 모의 객체를 반환하도록 테스트에서 구성 할 수있는 팩토리 또는 ServiceLocator를 사용하는 것입니다.

또 다른 방법은 적절한 격리 프레임 워크 또는 조롱 도구를 사용하는 것입니다. 이러한 도구는 거의 모든 현대 프로그래밍 언어 (Java, C #, Ruby 및 Python의 경우)에 존재합니다. 테스트 된 클래스가 종속성을 직접 인스턴스화하더라도 다른 클래스 / 유형의 구현에서 테스트중인 클래스를 분리 할 수 ​​있습니다.

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