2014-03-27 5 views
-1

누군가이 저장소 클래스를 올바르게 모의하는 법을 보여 주실 수 있습니까? 기본적으로 나는 서비스 계층을 쉽게 테스트 할 수 있도록 조롱하고 싶다. 오전 테스트 프로젝트에서 moq을 사용하여 # moq. 대부분 문제가있는 곳은 Query, Filter, Include 및 OrderBy 메소드에서 사용되는 가상 인터페이스 패턴입니다. Repository mock에 주입 한 RepositoryQuery를 제대로 반환 할 수 있도록 어떻게 모의합니까?moq을 사용하여이 클래스들을 모의하는 방법

아래에 표시된 코드는 데이터베이스와 통신하는 데이터베이스 계층의 일부이므로 외부 의존성없이 내 서비스 계층을 쉽게 테스트 할 수 있도록 조롱하고 싶습니다.

public class Repository<TEntity> : IRepository<TEntity> where TEntity : BaseEntity 
    { 
     private readonly Guid _instanceId; 
     private readonly DbSet<TEntity> _dbSet; 
     private readonly IDbContext _context; 

     public Repository(IDbContext context) 
     { 
      _context = context; 
      _dbSet = context.Set<TEntity>(); 
      _instanceId = Guid.NewGuid(); 
     } 

     public virtual IRepositoryQuery<TEntity> Query() 
     { 
      var repositoryGetFluentHelper = new RepositoryQuery<TEntity>(this); 
      return repositoryGetFluentHelper; 
     } 

     internal IQueryable<TEntity> Get(
      List<Expression<Func<TEntity, bool>>> filters = null, 
      Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
      List<Expression<Func<TEntity, object>>> includeProperties = null, 
      int? page = null, 
      int? pageSize = null) 
     { 
      IQueryable<TEntity> query = _dbSet; 

      if (includeProperties != null) 
      { 
       includeProperties.ForEach(i => query = query.Include(i)); 
      } 

      if (filters != null && filters.Any()) 
      { 
       query = filters.Aggregate(query, (current, filter) => current.Where(filter)); 
      } 

      query = orderBy != null ? orderBy(query) : query.OrderBy(a => a.Id); 

      if (page != null && pageSize != null) 
      { 
       query = query 
        .Skip((page.Value - 1)*pageSize.Value) 
        .Take(pageSize.Value); 
      } 
      return query; 
     } 


    } 
+1

. 우리는 당신을 도울 수 없습니다. 그것은 당신에게 순전히 달려 있습니다. 사람들이 각 테스트에 대해 모의 한 내용을 보려면 기본적인 조롱 자습서를 찾아보십시오. 예를 들어, 하나의 기능을 테스트하기 위해서만 전체 저장소를 조롱하지 마십시오. –

+0

안녕하세요, 데이터 저장소와 통신하기 때문에 위의 코드 중 일부는 내 데이터 레이어에서 사용한 것이며 일부 기능 만 테스트하지 않고 전체 서비스 레이어를 테스트 할 수 있도록 완전히 모의하고 싶습니다. – Cizaphil

답변

2

public sealed class RepositoryQuery<TEntity> : IRepositoryQuery<TEntity> where TEntity : BaseEntity 
    { 

     private readonly List<Expression<Func<TEntity, object>>> _includeProperties; 
     private readonly Repository<TEntity> _repository; 
     private readonly List<Expression<Func<TEntity, bool>>> _filters; 
     private Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> _orderByQuerable; 
     private int? _page; 
     private int? _pageSize; 

     public RepositoryQuery(Repository<TEntity> repository) 
     { 
      _repository = repository; 
      _includeProperties = new List<Expression<Func<TEntity, object>>>(); 
      _filters = new List<Expression<Func<TEntity, bool>>>(); 
     } 

     public RepositoryQuery<TEntity> Filter(Expression<Func<TEntity, bool>> filter) 
     { 
      _filters.Add(filter); 
      return this; 
     } 

     public RepositoryQuery<TEntity> OrderBy(Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy) 
     { 
      _orderByQuerable = orderBy; 
      return this; 
     } 

     public RepositoryQuery<TEntity> Include(Expression<Func<TEntity, object>> expression) 
     { 
      _includeProperties.Add(expression); 
      return this; 
     }  

     public IQueryable<TEntity> Get() 
     { 
      return _repository.Get(_filters, _orderByQuerable, _includeProperties, _page, _pageSize); 
     } 

    } 

이는 희망이 당신의 구성 요소는 인터페이스 IRepositoryQuery<TEntity>IRepository<TEntity> 아니라 구체적인 구현 RepositoryQuery<TEntity>Repository<TEntity>에 따라 달라집니다. 그렇다면 Moq와 같은 단위 테스트 목적을위한 인터페이스에 대한 테스트 복식을 제공하십시오.

var mockQuery = new Mock<IRepositoryQuery<TEntity>>(); 

// perform any setup needed on mockQuery for the particular System Under Test 

var mockRepository = new Mock<IRepository<TEntity>>(); 

// perform any setup needed on mockRepository for the particular System Under Test 

// component that relies on query and repository 
// that is the System Under Test i.e. the focus of the unit test 
var systemUnderTest = new SystemUnderTest(mockRepository.Object, mockQuery.Object); 

관찰 결과; RepositoryQuery<TEntity>을 보면, 구체적인 구현 방법 인 RepositoryQuery<TEntity>에 반해서 메소드가 인터페이스 IRepositoryQuery<TEntity>을 반환해야한다고 생각합니다.

+0

둘 다 인터페이스를 가지고 있지만'RepositoryQuery '은 리포지토리 클래스의 도우미 역할을하기 때문에'Repository '에 밀접하게 연결되어있어서 혼란 스럽습니다. – Cizaphil

+0

@Cizaphil 그러면 인터페이스는 어떻게 생겼을까요? –

1

의 래퍼 인 경우 서비스 계층을 테스트하려면 IRepository을 조롱 할 필요가 없습니다. 그냥 IRepositoryQuery을 조롱하세요. 내가 SomeService.DoSomething 올바르게은 IRepositoryQuery.Get에서 얻는 결과를 처리하는 확인하고자한다고 가정

: 당신은 당신이 현재 실행중인 테스트에 완전히 의존 조롱 무엇

var mock = new Mock<IRepositoryQuery<SomeClass>>(); 
mock.Setup(o => o.Get(/* test parameters */)).Returns(/* result */); 

var myService = new SomeService(mock.Object); 
Assert.That(myService.DoSomething(), Is.EqualTo(/* expected result*/)); 
관련 문제