私は職場でプロジェクトを行っており、私の目標の一部は、テストドライブ開発アプローチを学び、適用することです。
EF コードの最初のリポジトリで動作するビジネス クラスを設計していますが、実際にデータベースにアクセスするのではなく、リポジトリのモックを作成したいと考えています。
次のリポジトリ インターフェイスが与えられた場合、MOQ のようなモック フレームワークを使用してこれを達成するにはどうすればよいですか? 課題は、他のエンティティを含めることができる Find メソッドをどのように moq するかということです。
public interface IRepository<T> where T : EntityBase, new()
{
ICollection<T> Find(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] fetchSelectors);
ICollection<T> Find(Expression<Func<T, bool>> predicate, int pageNumber, int size, Expression<Func<T, object>> orderBy, string sortOrder, out int count, params Expression<Func<T, object>>[] fetchSelectors);
ICollection<T> FindAll(params Expression<Func<T, object>>[] fetchSelectors);
ICollection<T> FindAll(int pageNumber, int size, Expression<Func<T, object>> orderBy, string sortOrder, out int count, params Expression<Func<T, object>>[] fetchSelectors);
void Save(T entity);
void Delete(T entity);
T Create();
}
これが私の汎用リポジトリの実装です。
public class GenericRepository<T> : IRepository<T> where T : EntityBase, new()
{
public GenericRepository(IDbContext context)
{
Guard.ArgumentNotNull(context, "context");
this.Context = context;
this.DbSet = this.Context.CreateDbSet<T>();
}
protected IDbContext Context
{
get;
set;
}
protected System.Data.Entity.IDbSet<T> DbSet
{
get;
set;
}
public virtual ICollection<T> Find(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] fetchSelectors)
{
return this.BuildQuery(predicate, fetchSelectors).ToList();
}
public virtual ICollection<T> FindAll(params Expression<Func<T, object>>[] fetchSelectors)
{
return this.BuildQuery(p => true, fetchSelectors).ToList();
}
public virtual void Save(T entity)
{
Guard.ArgumentNotNull(entity, "entity");
this.Context.SaveOrUpdate(entity);
}
public virtual void Delete(T entity)
{
Guard.ArgumentNotNull(entity, "entity");
this.DbSet.Remove(entity);
}
public T Create()
{
return this.DbSet.Create();
}
private IQueryable<T> BuildQuery(Expression <Func<T, bool>> predicate, params Expression<Func<T, object>>[] fetchSelectors)
{
var query = this.DbSet as IQueryable<T>;
if (fetchSelectors != null)
{
foreach (var fetchSelector in fetchSelectors)
{
query = query.Include(fetchSelector);
}
}
return query.Where(predicate);
}
public ICollection<T> Find(Expression<Func<T, bool>> predicate, int pageNumber, int size, Expression<Func<T, object>> orderBy, string sortOrder, out int count, params Expression<Func<T, object>>[] fetchSelectors)
{
count = (this.DbSet as IQueryable<T>).Count(predicate);
if (size < 1 || size > count)
{
throw new ArgumentOutOfRangeException("size");
}
var maxPageNumber = (count + size - 1) / size;
if (pageNumber < 1 || pageNumber > maxPageNumber)
{
throw new ArgumentOutOfRangeException("pageNumber");
}
if (sortOrder != "asc" && sortOrder != "desc")
{
throw new ArgumentException("sortOrder");
}
var skipCount = (pageNumber - 1) * size;
var query = BuildQuery(predicate, fetchSelectors);
query = sortOrder == "asc" ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
return query.Skip(skipCount).Take(size).ToList();
}
public ICollection<T> FindAll(int pageNumber, int size, Expression<Func<T, object>> orderBy, string sortOrder, out int count, params Expression<Func<T, object>>[] fetchSelectors)
{
return Find(p => true, pageNumber, size, orderBy, sortOrder, out count, fetchSelectors);
}
}
最後に、IDbContext は次のとおりです。
public interface IDbContext
{
void SaveOrUpdate<T>(T entity) where T : EntityBase;
IDbSet<TEntity> CreateDbSet<TEntity>() where TEntity: EntityBase;
}