2014-03-27 118 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*/));