2009-12-21 2 views
5

저는 Mocking에 처음 익숙하며 단위 테스트에 익숙하며 마침내 엄격한 TDD 방식으로 시작하는 새로운 프로젝트에 대해 글 머리 기호를 물지 않기로 결정했습니다. 그러나 프로토 타입에서 승격 된대로 테스트를 추가하는 데 필요한 하나의 서비스 클래스와 메서드가 있습니다.WCF 호출 (MSUnit + Moq)이있는 단위 테스트 서비스

내가 할 노력하고 무엇
public class PageService : IPageService 
{ 
    private readonly ITestService testServiceClient; 

    public PageService(ITestService testServiceClient) 
    { 
     this.testServiceClient = testServiceClient; 
    } 

    public Page GetPage(Guid websiteId, string pageKey) 
    { 
     Page builtPage = null; 

     // WCF SERVICE CALL I DO NOT WANT EXECUTING WHEN RUNNING UNIT TEST 
     // BUT RATHER WANT A BLANK NEW INSTANCE OF "PAGE" CREATED USING MOQ?? 
     var page = testServiceClient.GetPage(websiteId, pageKey); 

     if (page == null) 
      return null; 

     builtPage = new Page(); 

     [code here to build builtPage if input params ok] ... 

     return builtPage; 
    } 
} 

는, 하나 개의 테스트를 작성하고,이 잘하면 내가 확장 할 수 있습니다에서 :

나는이 특정 테스트에 불구하고 시작하는 모르는,이 클래스와 방법이 관여 GetPage(...) 테스트의 모든 순열을 꺼내지 만 첫 번째 테스트에서는 유효한 websiteId 및 이 전달되었는지 테스트하고 유효한 Page 인스턴스를 받으면 테스트를 수행합니다.

testServiceClient은 WCF 서비스 클라이언트로, 이것은 using() 문장으로 둘러 쌓여 있습니다.하지만 테스트를 위해 필요한 첫 번째 단계로 느껴지 듯이 의존성 삽입과 함께 진행되도록 희망에서 옮겼습니다. 내가 이해하는 것으로부터 가짜/조롱을해야 할 것입니다. testServiceClient.GetPage()이 알려진 메모리 내 데이터 세트를 반환하는 대신 wcf 클라이언트를 사용합니까? 잘만되면 나는 바른 길 위에있다. 그래서 여기

내 단위 테스트의 나의 초기 청사진이다 (당신이 MOQ의 최신 버전을 사용하지 않은 경우 내가 MOQ 프레임 워크를 사용하고, Setup()Expect()의 새로운 버전은 없음) :

/// <summary> 
/// Tests service returns a valid instance of type `Page` when a valid website and valid page key is tested. 
/// </summary> 
[TestMethod] 
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page() 
{ 
    // Arrange 
    Page page = null; 

    // Act 
    var newPage = new Page() { Title = "Mocked Version!?"}; 

    testServiceClient = new Mock<ITestService>(); 
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage); 

    service = new PageService(testServiceClient.Object); 
    page = service.GetPage(websiteId, "about-us"); 

    // Assert 
    Assert.IsInstanceOfType(page, typeof(Page), "Object was not of expected instance type."); 
} 

내가 더이 여기에서 어디로 가야하는지, 아니면 내가 올바른 길을 가고 있는지 생각해보십시오. 나는 위의 어떤 구문 오류가없는 확인할 수 있습니다, 나는 예외 받는가 : 그러나 나는 '돈, websiteIdpageKey이 유효로

System.ArgumentException: Invalid setup on a non-overridable member: 
x => x.GetPage(websiteId, "about-us"). 

내가 아는 건, 내 service.GetPage(...) 새로운 인스턴스를 반환 할 것입니다을 실제로 testServiceClient.GetPage() WCF 전화를 사용하고 싶습니다 ... 잘하면 조롱의 아이디어를 이해합니다. 그 서비스에서 testServiceClient.GetPage을 사용할 때 Moq을 통해 정확하게 말했는지, 실제로는 페이지의 새로운 인스턴스를 반환할까요?

모든 설명이 크게 도움이됩니다. 고마워요!

답변

4

나는 당신이 올바른 길을 가고 있다고 말할 것입니다. ITestService가 진정으로 인터페이스 인 경우 (이름으로 표시됨) 모방 할 수 있습니다.

그러나 설정을 정의 할 때 Moq는 사용자가 의도 한 방법을 식별 할 수 있어야하며 인터페이스에 존재하지 않는 방법을 나타내는 것처럼 보입니다.

ITestService 인터페이스를 표시하지 않았으며 websiteId 변수 유형도 알 수 없습니다.

Setup 메서드를 자세히 살펴보면이 메서드는 일반적인 메서드이므로 일반 매개 변수없이 호출 할 때 유형 추론이 진행됩니다.

내 생각에 websiteId이라는 선언은 GetPage 선언과 충돌합니다.당신이 관리하면, 어떤 경우

Page GetPage(Guid x, string y); 

과 동일하지 않습니다

Page GetPage(object x, string y); 

: 예를 들어, websiteIdobject로 선언되었다 경우, MOQ이 서명하는 방법 돌볼 것 설치 프로그램을 작동 시키면 단위 테스트에 대한 기본적인 생각이 잘된 것 같습니다.

[TestMethod] 
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page() 
{ 
    // Arrange 
    Page page = null; 

    // Act 
    var newPage = new Page() { Title = "Mocked Version!?"}; 

    testServiceClient = new Mock<ITestService>(); 
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage); 

    service = new PageService(testServiceClient.Object); 
    page = service.GetPage(websiteId, "about-us"); 

    // Assert 
    Assert.AreEqual(newPage, page); 
} 

공지 훨씬 더 가치 어설 : 모의 반환 된 인스턴스가 사용자가 설정 originall의 인스턴스와 동일한 지 확인하기 때문에 당신은 단지 인스턴스가 null이 아니라고 주장하는 것보다 더 많은 일을 할 수 있습니다.

+0

+1 멋진 답변 - @GONeale, Mark가 말한 것을 확인하기 위해 MOQ와 인터페이스를 사용하여 빠른 테스트를 실행했습니다. GetPage가 가상으로 선언되지 않은 구체적인 인스턴스를 조롱하는 것과 같은 일을하는 것처럼 보일 것입니다. –

+0

안녕하세요, 내 게시물을 읽을 시간을내어 주셔서 감사합니다. 잘 ITestService는 WCF 생성 서비스 클라이언트 (오른쪽 클릭 프로젝트 -> 서비스 참조 추가) 유형입니다. 이 점을 감안할 때 자동 생성 클래스와 마찬가지로 '가상'이라고 선언 할 수 있다고 생각하지 않습니다. 그러나 간단한 WCF 호출자 클래스를 만들고이를 가상으로 만들면 도움이 될까요? Assert 팁 주셔서 감사합니다. – GONeale

+0

'testServiceClient.Setup (x => x.GetPage (..))를 선언함으로써 올바르게 이해할 수 있는가? return (newPage)'는 그 메소드의 이름에 대한 모든 호출을 알려준다 (객체의 메소드가 실제로 새로운 * PageService (testServiceClient.Object)의 예제와 같은 매개 변수로 * 실제 * (wcf) 메서드를 실제로 실행하지 말고 대신 newPage 인스턴스를 반환하십시오. 그것이'가상'이 필요한 이유인가, 완전히 새로운 방법 내용으로 대체하는 것인가? – GONeale