2015-01-26 4 views
2

List<T>을 반환하는 async 메서드를 단위 테스트하고 있습니다. 이 메서드는 매핑 클래스/인터페이스에 대한 종속성이 있습니다. 내 단위 테스트에서는 moq을 사용하여 매핑 클래스를 조롱하고 있습니다. 테스트가 제대로 실행되고 반환 된 목록에 항목이 있지만 항목 값이 null입니다. 나는 매핑 클래스 메서드를 올바르게 stubbed-out하지 않았기 때문에 문제가 있다고 생각합니다. 필자는 테스트 경험이별로 없기 때문에 어떤 지침도 환영합니다.Moq를 사용하여 단위 테스트

시험 방법 : 나는 시험 해요 그

[TestMethod] 
[TestCategory("CSR.Data.Tests.Services.ServiceSearchTest")] 
public void SearchAccount() 
    { 
     // Arrange     
     var mapper = new Mock<CSR.Data.Mapping.Interfaces.IMapper<Account, AccountDTO>>(); 

     mapper.Setup(i => i.Initialize()); 
     mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns(It.IsAny<Account>); 
     mapper.Setup(i => i.DomainToDto(It.IsAny<Account>())).Returns(It.IsAny<AccountDTO>); 

     var service = new ServiceSearch(null,mapper.Object);   
     string accountNumber = "123"; 
     string accountName = ""; 

     // Act 
     var results = service.SearchAccount(accountNumber, accountName);    

     // Assert 
     Assert.IsTrue(results.Result.Count >= 1); 
     } 

방법/등급 :

public class ServiceSearch : IServiceSearch 
    { 
    public ServiceSearch(IMapper<Claim, ClaimDTO> claimMapper, IMapper<Account, AccountDTO> accountMapper) 
      { 
       _claimMapper = claimMapper; 
       _accountMapper = accountMapper; 
      } 

    public async Task<List<AccountDTO>> SearchAccount(string accountNumber, string accountName) 
      { 
       var accounts = new List<Account>(); 
       var accountDTOs = new List<AccountDTO>(); 
       var results = await Task.Run(() => base.AccountSearch(accountNumber, accountName).Result); 

       if (results != null && results.Count > 0) 
       { 
        //Map DH to Domain 
        _accountMapper.Initialize(); 

        foreach (AccountSearchResult result in results) 
        { 
         accounts.Add(_accountMapper.ToDomain(result)); 
        } 

        //Map Domain to DTO 
        foreach (Account account in accounts) 
        { 
         accountDTOs.Add(_accountMapper.DomainToDto(account)); 
        } 
       } 
       return accountDTOs; 
      } 
} 
+0

'async' 코드에서'Result' (그리고 아마도'Task.Run')를 사용하지 말아야합니다. –

+0

@StephenCleary ... 작업의 가치를 원하지 않습니까? Task에 문제가있어. 여기서 뛰었 니? 나는 그것이 가치 있다고 생각한다면 또 다른 질문을 할 것이다. –

+0

'await'은 결과를 검색하기위한 적절한 메커니즘입니다. 'Task.Run'은 UI 계층에서 CPU 바운드 메소드를 호출하는 데에만 사용해야하며이 코드에서는 그렇지 않습니다. –

답변

0

당신하지 실제로는 설정은 ".Returns"호출 객체. 실제로 값이있는 객체를 갖기 위해 ".Returns"를 설정해야합니다.

+0

Steve Mitcham에 대한 제 응답을 참조하십시오. –

1

테스트 객체를 작성하고 결과를 모으는 데 많은 시간을 할애하기 때문에 Mock 객체를 사용하는 가장 좋은 장소는 아닙니다. 설치 호출의 문제점은 사용자가 결과로 다시 보내도록 아무 것도 구성하지 않았기 때문입니다. 원래 올바른 예는 다음과 같습니다

// you would fully configure this object 
AccountDTO expectedResult = new AccountDTO(); 

mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns(expectedResult); 

지금 당신이 다른 입력에 대해 서로 다른 accountDTOs을 구성하는 설정을 사용할 수 있습니다.

또한 전화 테스트 시간에 계정 생성하기 위해 콜백을 구성하여 매퍼 실행하거나 생성하는 비용이하지 않는

mapper.Setup(i => i.ToDomain(It.IsAny<AccountSearchResult>())).Returns<AccountSearchResult>(sr => { 
    // build and return your dto here 
}); 

그러나, 나는 당신이 그냥 완전히 있는지 확인 것이 더 좋을 거라고 생각을 테스트를 거쳐 받아 들여진 다음 DTO를 조롱하지 않고 직접 생성하는 데 사용합니다.

+0

실례를 삭제하고 IMapper 인스턴스를 사용했는데 정상적으로 작동합니다. 나는 이것을 할 수는 있지만 모의이 효과가없는 이유를 이해하지 못한다. 조이는 것이 꽉 조이는 것을 피하기 위해 이것을하는 올바른 방법이 아닙니까? 또한 null 속성 값을 사용하여 클래스를 제안하고 반환 할 때 반환 값을 변경했습니다. 이러한 클래스를 수동으로 채워야 작동시킬 수 있습니까? –

+0

모의 할 시점과 기존 구현을 사용해야하는 시점 사이의 경계는 저에게 희소식입니다. 나는 시스템을 조롱했을 때 테스트를 최신으로 유지하려고 많은 시간을 보냈습니다. 데이터 매핑과 같은 것을 사용하면 mapper 클래스의 구현에 의존하지 않는다는 점에서 여전히 '느슨한 결합'이 있지만 입력 및 출력의 구조에 의존합니다. 만약 당신이하고있는 일이 다른 타입의 인스턴스들간에 프로퍼티를 복사하는 것이라면, 그것은 정말로 당신의 모든 모의 작업을 수행 할 것입니다. –

+1

@BigDaddy 네, 수동으로 클래스를 채워야합니다. (또는 기존 구현을 사용하십시오.) 참 격리를 원하면 수동으로 채워야합니다. –

관련 문제