2012-10-10 2 views
1

나는 이걸 가지고 내 머리카락을 잡아 당길거야. 나는 보았고 Microsoft Moles에서 부분 스텁을 만들고 사용하는 간단하고 명확한 예를 찾을 수 없습니다. 어쩌면 내가 잃어버린 somethimg, 또는 내 코드를 잘 만들지 않을 수 있지만이 작동하도록 할 수 없습니다.Microsoft Moles에서 부분 스텁 만들기

public class AccountService : IAccountService { 
     private readonly webServiceProxy IExternalWebServiceProxy; 

    public AccountService(IExternalWebServiceProxy webServiceProxy) { 
     this.webServiceProxy = webServiceProxy; 
    } 

    public List<AccountModel> GetAccounts(string customerId) { 
     var returnList = new List<AccountModel>(); 
     var xmlResponse = webServiceProxy.GetAllCustomerAccounts(customerId); 

     var accountNodes = xmlResponse.SelectNodes("//AccountNodes"); 
      if (accountNodes != null) 
      { 
       foreach (XmlNode node in accountNodes) 
       { 
        var account = this.MapAccountFromXml(node); 

        if (!string.IsNullOrEmpty(account.AccountNumber)) 
        { 
         returnList.Add(account); 
        } 
       } 
      } 

      return returnList; 
    } 

    public AccountModel MapAccountFromXml(XmlNode node) { 
     if (!IsValidAccount(node) { 
      return null; 
     } 

     // This performs a lot of XML manipulation getting nodes based on attributes 
     // and mapping them to the various properties of the AccountModel. It's messy 
     // and I didn't want it inline with the other code. 

     return populatedAccountModel; 
    { 

    public bool IsValidAccount(XmlNode node) 
    { 
     var taxSelectValue = node.SelectSingleNode("//FORMAT/Field[@taxSelect='1']").First().Value; 
     var accountStatus = // similar to first line in that it gets a single node using a specific XPath 
     var maturityDate = // similar to first line in that it gets a single node using a specific XPath 
     var maturityValue = // similar to first line in that it gets a single node using a specific XPath 

     return taxSelectValue != string.Empty && taxSelectValue != "0" && (accountStatusValue != "CL" || (maturityDate.Year >= DateTime.Now.AddYears(-1).Year)); 
    } 
} 

는 내가하고 싶은 것은 내 GetAccounts() 메소드를 테스트 할 수 있습니다 :

여기 (간체) 내 수업입니다. IExternalWebServiceProxy 호출을 스텁 (stub)하여 가짜 XML을 반환 할 수 있지만 GetAccounts() 메서드가 MapAccountFromXml()을 호출하고 IsValidAccount()를 호출하기 때문에 내 서비스에서 내부 호출이 발생합니다.

아마도 해결책은 길고 관련이있는 MapAccountFromXml() 및 IsValidAccount() 코드를 분리하여 GetAccount() 호출에 인라인으로 넣는 것에 대해 걱정하지 않아도되지만 코드 가독성을 위해 코드를 분리하여 남겨 두는 것이 좋습니다.

내 두더지 어셈블리가 만든, 나는 내 문제는 내가 다음 MapAccountFromXml 및 IsValidAccount에 대한 내부 호출을 재정의하는 방법을 몰라이

var stubWebService = SIExternalWebServiceProxy { 
     GetAllCustomerAccounts = delegate { 
      return SomeHelper.GetFakeXmlDocument(); 
     } 
} 

var stubAccountService = new SAccountService() { callsBase = true; } 

처럼 내 클래스의 스텁 버전을 만들 수있어 나는 Unit Test가 thos 메소드를 테스트하는 것을 원하지 않는다. 테스트를 위해 GetAccounts를 분리하고 싶다. 메소드가 부분 스텁에서 오버라이드 될 가상 메소드가 필요하지만 어쨌든 테스트하고 싶은 메소드의 기반을 호출하는 동안 몇 가지 메소드를 오버라이드하는 스텁을 만드는 방법을 찾을 수 없습니다.

답변

1

피어가 옳은 길에 나를 두었습니다. 감사합니다.

제가 찾고 있던 것은 두더지에서 우회로라고합니다. 오히려 MAccountService은이

var accountService = new AccountService(); 

MAccountService.AllInstances.MapAccountFromXmlXmlNode = delegate { 
    return new AccountModel(); 
}; 

같은 내가 조롱하고 싶었던 방법에 대한 모든 호출을 내 AccountService에의 인스턴스를 만든 다음 우회 내가 할 필요가 무엇

var stubAccountService = new SIAccountService(); 

된 사용하여 인터페이스를 스텁에 비해 당신이 당신의 집을 몰살 할 때 Moles가 제공했습니다.이 유일한 누락 된 부분은이 작업을 위해 당신이 당신의 시험 방법에 다음 속성을 추가 할 필요가 있다는 것입니다 :이 로컬 나를 위해 일한

[HostType("Moles")] 

했지만 결국 내가 빌드 TFS 자동화 않는하는데 문제가 있었다 코뿔소 모의 객체를 보면서

UPDATE는

난 그냥이 일을 다른 방법에 비틀 거렸다.

이제
var accountService = new SAccountService(); 
accountService.MapAccountFromXmlXmlNode = delegate 
    { 
     return new AccountModel(); 
    } 

내가

accountService.GetMemberAccounts(); 

를 호출 할 수 있습니다 및 AccountService에는 MapAccountFromXml과의 호출을 할 때 조롱되는 클래스의 메소드가 가상을 경우 당신은 다음과 같이 모의에서 그들을 대체 할 수 있습니다 그것은 스텁에 의해 잡히고 내가 필요하다고 생각하는대로 처리됩니다. HostType을 망칠 필요가 없으며 매력처럼 작동합니다.

0

당신이 수업에서 클래스를 테스트하려면 IsValidAccount 및 MapAccountFromXml 메서드에 대한 두더지를 만들어 두더지를 사용하십시오. 또는 스텁을 사용하여 스텁을 호출하여 스텁이 기본을 사용하여 원래의 메서드를 호출하도록 할 수 있습니다. 또는 내가 더 멋진 솔루션이라고 생각하는 것은 스텁하려는 메서드를 재정의하는 테스트 클래스를 작성하는 것입니다 (이것은 스텁이 수행하는 것과 동일합니다).

public class TestHelperAccountService : AccountService { 

    public override AccountModel MapAccountFromXml(XmlNode node) { 
     return new AccountModel(){ 
        //Accountmodelstub 
       }; 
    { 

    public override bool IsValidAccount(XmlNode node) 
    { 
     return true; 
    } 
} 

이렇게하면 GetAccount 메서드가 전체 발급으로 실행되는 TestHelperAccountService 클래스에서 GetAccount 메서드에 대한 테스트를 수행 할 수 있습니다. MapAccountFromXml과 같은 메소드에 대해 동일한 작업을 수행하여 개별적으로 테스트 할 수 있습니다.

+0

내 테스트 클래스를 만든 경우 테스트 한 메서드 당 하나의 클래스가 필요합니까? GetAccount를 테스트하려면 MapFromAccount 및 IsValidAccount가 스텁 된 클래스가 필요합니다. MapFromAccount를 테스트하기 위해서는 IsValidAccount가 스텁 된 다른 테스트 클래스와 IsValidAccount를 테스트하는 세 번째 클래스가 필요합니다. 차라리 특정 메서드에 대한 기반을 호출하는 스텁을 갖고 싶지만, Moles에서이를 수행하는 방법을 알아낼 수는 없습니다. 설명서에 명확한 예제가없는 것 같습니다. –

+0

클래스를 스터핑하여 테스트 할 메소드 delegete에 기본 구현을 호출하고 스텁하려는 메소드에 대한 스텁을 만들 수도 있습니다. – Peter