私はEntity Framework 5でASP.NET MVC 4を使用しています。既存のテーブルをモデルクラスにマップするためのモデルクラスとEntityマップがあります。すべてこれはうまく動作し、うまく動作します。Entity Framework 5を使用した作業単位と汎用リポジトリ
今私はこれを嘲笑したい。 DataContextを使用し、汎用リポジトリを使用する作業単位を作成しました。その上で、私は一度に多くのリポジトリからデータを取得し、DataContextの1つのインスタンスを必要とするだけのサービスを構築しました。これも素晴らしいです。
問題が発生しました:私は模擬データを使ってサービスをテストしたいと思います。 Unit Of Workインスタンスを作成するときに、実際のDataContextの代わりにmockedされたDataContextを挿入できるようにします。
私はIContextインターフェイスを作成しようとしましたが、実際のDataContextはそれを実装しましたが、DbSetの問題に遭遇しました。 IDbSetを使ってFakeDbSetを作成しようとしましたが、成功しませんでした。私はまた、IDbSetでコンテキストを嘲笑し、FakeDbSetを使うことは悪いアプローチであることをインターネット上で読んでいます。
これを達成するための最良の方法は何ですか?私が今保有しているのは、保持したい動作ですが、DataContextのModelクラスからデータをモックすることが本当に好きです。
私は、Entity Frameworkに既にUnit Of Workの動作が付属していることを認識しており、その上に特別な動作を追加する必要はありません。しかし、私はすべてのリポジトリ(UnitOfWorkクラスと呼ばれる)を追跡する別のクラスの内部を包み込みたいと思っていました。
編集:私はLINQとEntity Frameworkの両方で私のソリューションを説明する2つの記事を書いています。
http://gaui.is/how-to-mock-the-datacontext-linq/
http://gaui.is/how-to-mock-the-datacontext-entity-framework/
ここに私のコードは次のとおりです。
IRepository.cs
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
T GetById(long Id);
IEnumerable<T> All();
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
}
IUnitOfWork.cs
public interface IUnitOfWork : IDisposable
{
IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
void Save();
}
Repository.cs
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDbContext _context;
private readonly IDbSet<T> _dbset;
public Repository(IDbContext context)
{
_context = context;
_dbset = context.Set<T>();
}
public virtual void Add(T entity)
{
_dbset.Add(entity);
}
public virtual void Delete(T entity)
{
var entry = _context.Entry(entity);
entry.State = System.Data.EntityState.Deleted;
}
public virtual void Update(T entity)
{
var entry = _context.Entry(entity);
_dbset.Attach(entity);
entry.State = System.Data.EntityState.Modified;
}
public virtual T GetById(long id)
{
return _dbset.Find(id);
}
public virtual IEnumerable<T> All()
{
return _dbset;
}
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return _dbset.Where(predicate);
}
}
UnitOfWork.cs
public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new()
{
private readonly IDbContext _ctx;
private Dictionary<Type, object> _repositories;
private bool _disposed;
public UnitOfWork()
{
_ctx = new TContext();
_repositories = new Dictionary<Type, object>();
_disposed = false;
}
public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
if (_repositories.Keys.Contains(typeof(TEntity)))
return _repositories[typeof(TEntity)] as IRepository<TEntity>;
var repository = new Repository<TEntity>(_ctx);
_repositories.Add(typeof(TEntity), repository);
return repository;
}
public void Save()
{
_ctx.SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
_ctx.Dispose();
}
this._disposed = true;
}
}
}
ExampleService.cs
public class ExampleService
{
private IRepository<Example> m_repo;
public ExampleService(IUnitOfWork uow)
{
m_repo = uow.GetRepository<Example>();
}
public void Add(Example Example)
{
m_repo.Add(Example);
}
public IEnumerable<Example> getAll()
{
return m_repo.All();
}
}
ExampleController。CS
public IEnumerable<Example> GetAll()
{
// Create Unit Of Work object
IUnitOfWork uow = new UnitOfWork<AppDataContext>();
// Create Service with Unit Of Work attached to the DataContext
ExampleService service = new ExampleService(uow);
return service.getAll();
}
私はまた、あなたが言及したのと同じ問題を抱えています。しかし、IDbContextとIDbContextを実装する具体的なクラスのコードを投稿できますか?これは私をたくさん助けます。前もって感謝します。 – NoobDeveloper
@Nexus [http://gaui.is/how-to-mock-the-datacontext-entity-framework/](http://gaui.is/how-to-mock-the-datacontextentity-framework/ ) – Gaui
@Gauiコントローラの代わりに 'ExampleService'クラスの中に' UnitOfWork'インスタンスを作成するほうがよいでしょうか?そうすれば、あなたのコントローラは必要な 'DbContext'を知る必要がなくなり、それをサービスに残します。 – GFoley83