2011-03-24 6 views
11

내가 수업을C++의 모의 객체는 항상 가상 메소드 또는 템플릿이 필요합니까?

class Inner { 
    public: 
    void doSomething(); 
}; 

class Outer { 
    public: 
    Outer(Inner *inner); // Dependency injection. 

    void callInner(); 
}; 

적절한 단위 테스트 나는 Inner에 대한 검사를해야한다라고 가정하자. 그렇다면 Outer/Inner 대신 Outer이 추가 된 기능에 대한 단위 테스트를 수행 할 수 있도록 이 아닌 MockInner을 사용하는 Outer에 대한 테스트를 수행해야합니다. 이렇게하려면

Googletest이 같은 순수한 추상 클래스 (인터페이스)로 Inner를 돌려 제시하는 것 같다

// Introduced merely for the sake of unit-testing. 
struct InnerInterface { 
    void doSomething() = 0; 
}; 

// Used in production. 
class Inner : public InnerInterface { 
    public: 
    /* override */ void doSomething(); 
}; 

// Used in unit-tests. 
class MockInner : public InnerInterface { 
    public: 
    /* override */ void doSomething(); 
}; 

class Outer { 
    public: 
    Outer(Inner *inner); // Dependency injection. 

    void callInner(); 
}; 

그래서, 생산 코드에서, 내가 Outer(new Inner)을 사용; 테스트 중에는 Outer(new MockInner)입니다.

확인. 이론적으로는 좋았지 만 코드 전체에서이 아이디어를 사용하기 시작했을 때 모든 괴물을위한 순수한 추상 클래스를 만들었습니다. 불필요한 가상 디스패치 때문에 약간의 런타임 성능 저하를 무시할 수있는 경우에도 보일러 플레이트 타이핑이 많이 있습니다.

다른 방법은 다음과 같이 템플릿을 사용하는 것입니다 : 이것은 보일러 도금 및 불필요한 가상 파견을 피할 수

class Inner { 
    public: 
    void doSomething(); 
}; 

class MockInner { 
    public: 
    void doSomething(); 
}; 

template<class I> 
class Outer { 
    public: 
    Outer(I *inner); 

    void callInner(); 
}; 

// In production, use 
Outer<Inner> obj; 

// In test, use 
Outer<MockInner> test_obj; 

; 하지만 지금은 전체 코드베이스가 괴상한 헤더 파일에있어 소스 구현을 숨길 수 없게됩니다 (템플릿 컴파일 오류와 긴 빌드 시간은 물론입니다).

올바른 단위 테스트를 수행하는 유일한 방법은 가상 및 템플릿이라는 두 가지 방법입니까? 적절한 단위 테스트를 수행하는 더 좋은 방법이 있습니까?

적절한 단위 테스트를 통해, 나는 을 의미합니다. 각 단위 테스트는 해당 유닛에 의해 도입 된 기능 만 테스트하지만 유닛의 종속성은 테스트하지 않습니다..

답변

5

나는 당신이 생각하지 않는다 은 테스트 한 클래스의 모든 의존성을 실제로 조롱한다. 그것을 창조하거나, 사용하거나 감지하는 것이 복잡하다면, 그렇다. 또한 DB, 네트워크 또는 파일 시스템과 같은 불필요한 외부 리소스에 직접 의존하는 경우.

그러나이 중 아무 것도 문제가되지 않는다면 IMO에서 인스턴스를 직접 사용해도됩니다. 이미 유닛 테스트를했기 때문에 예상대로 작동하고 상위 레벨 유닛 테스트를 방해하지 않는다고 합리적으로 확신 할 수 있습니다.

나는 개인적으로 단위 테스트 순진 주의자들에 의해 이상적으로 설정되는 것보다 작업 단위 테스트와 단순하고 깨끗한 유지 보수가 가능한 디자인을 선호합니다.

각 단위 테스트는 해당 유닛이 도입 한 기능 만 테스트하지만 유닛의 종속성은 테스트하지 않습니다. 기능성 기능성을 테스트 및 를 사용

매우 다른 두 가지입니다.

+0

저는 개인적으로 단위 테스트 순결 자들이 이상적으로 설정 한 것보다 작업 단위 테스트와 단순하고 깨끗하며 유지 보수가 가능한 디자인을 선호합니다. 나는이 반응을 좋아한다. – kirakun

2

또한 내부의 인스턴스를 직접 사용하는 것이 좋다고 생각합니다. 내 문제는 내 코드의 일부가 아닌 외부 객체를 조롱하는 것입니다 (정적 라이브러리 또는 DLL을 통해 제공되며 경우에 따라 타사에서 제공됨). 모의 DLL이나 라이브러리를 동일한 클래스 이름으로 다시 작성한 다음 테스트를 위해 다르게 링크하려고합니다. 외부 종속성의 헤더 파일을 수정하여 "가상"을 추가하는 것은 나에게 받아 들일 수없는 것처럼 보인다. 누구에게 더 좋은 해결책이 있습니까?

관련 문제