2009-08-03 8 views
3

일부 외부 종속성을 조롱하고 있으며 다른 제 3 자 클래스의 인스턴스를 생성자로 사용하는 제 3 자 클래스에 문제가 있습니다. 잘하면 SO 커뮤니티 나에게 어떤 방향을 줄 수 있습니다.Moq를 조롱 할 수 있습니까?

의 mock 인스턴스를 생성자로 사용하는 SomeRelatedLibraryClass의 모의 인스턴스를 만들고 싶습니다. 어떻게하면 SomeRelatedLibraryClass을 이런 식으로 조롱 할 수 있습니까?

되찾기 코드 ... 여기

내가 내 테스트 콘솔 응용 프로그램에서 사용하고 주요 방법이다. (여기

public class MyClass 
{ 
    private SomeLibraryClass _SLC; 

    public MyClass(string constructMsg) 
    { 
     _SLC = new SomeLibraryClass(constructMsg); 
    } 

    public virtual void WriteMessage(string message) 
    { 
     _SLC.WriteMessage(message); 
    } 
} 

내가 함께 일하고 제 3 자 클래스의 두 가지 예는 다음과 같습니다

public static void Main() 
{ 
    try 
    { 
     SomeLibraryClass slc = new SomeLibraryClass("direct to 3rd party"); 
     slc.WriteMessage("3rd party message"); 
     Console.WriteLine(); 

     MyClass mc = new MyClass("through myclass"); 
     mc.WriteMessage("myclass message"); 
     Console.WriteLine(); 

     Mock<MyClass> mockMc = new Mock<MyClass>("mock myclass"); 
     mockMc.Setup(i => i.WriteMessage(It.IsAny<string>())) 
      .Callback((string message) => Console.WriteLine(string.Concat("Mock SomeLibraryClass WriteMessage: ", message))); 

     mockMc.Object.WriteMessage("mock message"); 
     Console.WriteLine(); 
    } 
    catch (Exception e) 
    { 
     string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString()); 
     Console.WriteLine(error); 
    } 
    finally 
    { 
     Console.Write("Press any key to continue..."); 
     Console.ReadKey(); 
    } 
} 

내가 한 타사 클래스를 포장하고 Moq'd 될 수 있도록하는 데 사용한 클래스입니다 이러한) 편집 할 수 없습니다 :

public class SomeLibraryClass 
{ 
    public SomeLibraryClass(string constructMsg) 
    { 
     Console.WriteLine(string.Concat("SomeLibraryClass Constructor: ", constructMsg)); 
    } 

    public void WriteMessage(string message) 
    { 
     Console.WriteLine(string.Concat("SomeLibraryClass WriteMessage: ", message)); 
    } 
} 

public class SomeRelatedLibraryClass 
{ 
    public SomeRelatedLibraryClass(SomeLibraryClass slc) 
    { 
     //do nothing 
    } 

    public void WriteMessage(string message) 
    { 
     Console.WriteLine(string.Concat("SomeRelatedLibraryClass WriteMessage: ", message)); 
    } 
} 

답변

2

AFAIK를, 당신이 밖으로 조롱하려는 클래스는 가상 또는 인터페이스가 아닌 경우 - 당신은 MOQ 그것을 조롱 수 없습니다. 제 3 자 라이브러리가 수업을 구현하지 않으면 운이 나쁘다고 생각합니다.

10

Gateway 패턴을 사용하는 것이 좋습니다. SomeRelatedLibraryClass에 직접 의존하는 대신 ISomeRelatedLibraryClassGateway 인터페이스를 만듭니다. ISomeRelatedLibraryClassGateway에서 같은 서명의 메서드로 호출해야하는 모든 SomeRelatedLibraryClass 메서드를 노출합니다.

public interface ISomeRelatedLibraryClassGateway { 
    void WriteMessage(string message); 
} 

그런 다음 루트 모든 타사 클래스를 호출 구현 만들 : SomeRelatedLibraryClass에 달려 앱에서 클래스는 이제 대신 ISomeRelatedLibraryClassGateway에 따라 달라질 수 있습니다 이제

public class SomeRelatedLibraryClassGateway : ISomeRelatedLibraryClassGateway { 
    private readonly SomeRelatedLibraryClass srlc; 
    public SomeRelatedLibraryClassGateway(SomeRelatedLibraryClass srlc) { 
    this.srlc = srlc; 
    } 

    void ISomeRelatedLibraryClassGateway.WriteMessage(string message) { 
    srlc.WriteMessage(message); 
    } 
} 

을,이 인터페이스입니다 조롱하기 쉽다. SomeRelatedLibraryClassGateway 클래스에는 실제로 단위 테스트가 필요하지 않습니다. 그것이하는 모든 것은 통과 통화입니다. 은 기능 테스트에서을 테스트해야하지만 mock없이 기능 테스트를 수행 할 수 있습니다.

희망이 도움이됩니다.

+0

실제로 문제는 SomeLibraryClass 유형의 매개 변수 인 SomeRelatedLibraryClass를 조롱해야한다는 것입니다. 게이트웨이 패턴을 통해이 클래스를 더 쉽게 조롱 할 수있는 방법이 명확하지 않습니다. 일반적으로 외부 종속성을 통합 할 때 게이트웨이 패턴을 사용하지만이 예제에서는 인터페이스 정의 및 구현을 생략했지만 문제와 관련이 없다고 생각합니다. –

+1

요점은 SomeRelatedLibraryClass를 조롱하는 것을 피하는 것입니다. 게이트웨이 패턴을 사용하면 SomeRelatedLibraryClass를 조롱하는 것을 피할 수 있습니다 (대부분의) 코드가 직접 의존하지 않기 때문입니다. 이것은 코드를 리팩터링하여 테스트하기 쉽도록 한 예입니다. –

관련 문제