2014-03-27 113 views
-1

請有人告訴我如何正確地模擬此存儲庫類。基本上我想嘲笑它,這樣我就可以輕鬆測試我的服務層。我的moq在我的測試項目中使用c#moq。在Query,Filter,Include和OrderBy方法中使用的虛擬接口模式中,大部分存在問題。我如何嘲笑它,以便它可以返回我注入到我的Repository模擬中的正確的RepositoryQuery。如何使用moq模擬這些類

如下所示的代碼是與數據庫通信我的數據庫層的一部分,所以我想嘲笑它,這樣我可以輕鬆無對外依存度擔心測試我的服務層。

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); 
     } 

    } 

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

你嘲笑什麼是完全依賴於您當前運行的考驗。我們無法幫助你..那完全取決於你。查看基本的嘲笑教程,以瞭解人們爲每個測試嘲笑的內容。例如:你不會嘲笑整個Repository只是爲了測試一個函數。 –

+0

嗨,上面的一些代碼是我在我的數據層中使用的,因爲它與數據存儲通信,我想完全嘲笑它,這樣我可以測試不僅僅是一個功能,而是我的整個服務層。 – Cizaphil

回答

2

希望您的組件依賴的接口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>,我認爲這些方法應該返回接口IRepositoryQuery<TEntity>而不是具體的實現RepositoryQuery<TEntity>

+0

它們都有接口,但是'RepositoryQuery '因爲它充當一個輔助的倉儲類是緊耦合到'庫',那是什麼讓我感到困惑。 – Cizaphil

+0

@Cizaphil接口是什麼樣子呢? –

1

如果IRepositoryQueryIRepository的包裝,那麼 - 測試你的服務層 - 你不需要模擬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*/));