Насколько я знаю, такого интерфейса нет.Даже если бы это было так, для реализации интерфейса потребовалось бы немало усилий.
Причина, по которой вы запрашиваете интерфейс IContext
, не в том, что вам нравятся интерфейсы, а в том, что вы хотите создать Фасад: пользователивашего интерфейса будет думать, что они имеют дело с реальной базой данных, в то время как на самом деле они будут иметь дело с вашей поддельной базой данных, вероятно, для модульного теста.
Это довольно трудоемкая реализация всех функциональных возможностей класса DbContext
и, что более важно, класса DbSet<...>
, особенно если вы хотите использовать элементы как DbContext.ChangeTracker
и DbContext.Database
.
Если вам нужен быстрый и простой метод для проверки вашего исходного почти неизмененного кода, яхотел бы получить пакет nuget, представляющий базу данных в памяти, например Nuget Effort
Таким образом, никто, даже структура сущностей, не узнает, что вы будете использовать фальшивкубаза данных.
class MyDbContext : DbContext
{
// probably already existing constructors:
public MyDbContext() : base (...) { }
public MyDbContext(string nameOrConectionString : base (nameOrConnectionString) { }
// extra constructor for Effort, uses existing base constructor
public MyDbContext(DbConnection existingConnection) : base(existingConnection) { }
... // DbSets etc
}
Использование:
const string unitTestDbName = "Db for Unit Tests";
DbConnection inMemoryDbConnection = Effort.DbConnectionFactory.CreatePersistent(testDbName);
using (var dbContext = new MyDbContext(inMemoryDbConnection))
{
// fill the database with test data that your test code expects
...
dbContext.SaveChanges();
}
Таким образом, ничего из вашего исходного кода не будет адаптировано для ваших модульных тестов.Использовать его довольно просто, особенно если вы знакомы со стандартным использованием инфраструктуры сущностей
Однако, если вы думаете, что можете доверять инфраструктуре сущностей и хотите протестировать свой код без использования инфраструктуры сущностей, вы можете создатьАдаптер для вашей базы данных.
Приятно то, что если в будущем вы решите больше не использовать Entity Framework или, возможно, даже не базу данных, а какой-то другой метод архивации, ваш код все равно будет работать.Недостаток: вы больше не можете использовать темные углы структуры сущностей.
Идея состоит в том, чтобы создать интерфейс архива и класс архива.Стандартный класс Archive имеет DbContext.
public interface IArchive : IDisposable
{
IQueryable<School> Schools {get; set;}
IQueryable<Teacher> Teachers {get; set;}
IQueryable<Student> Students {get; set;}
}
public class Archive : IArchive, IDisposable
{
private readonly DbContext = new SchoolDbContext(...);
public IQueryable<School> Schools => this.DbContext.Schools;
public IQueryable<Teacher> Teachers => this.DbContext.Teachers;
public IQueryable<Student> Students => this.DbContext.Students;
public int SaveChanges()
{
return this.DbContext.SaveChanges();
}
// TODO: Dispose disposes the DbContext
}
Вы создаете специальный архив для своих тестов:
class TestArchive : IArchive
{
private readonly List<School> schools = new List<School>();
private readonly List<Student> students = new List<Student>();
...
public IQueryable<Student> Students => this.students.AsQueryable();
...
public int SaveChanges() {return 1;}
}
Где-то, где вам нужно будет указать свой код для создания экземпляра вашего поддельного архива,вместо вашего реального архива.Это делается с использованием фабричного шаблона:
interface IArchiveFactory
{
IArchive Create();
}
class ArchiveFactory : IArchiveFactory
{
public IArchive Create()
{
return new MyDbContext(...);
}
}
class TestArchiveFactory : IArchivedFactory
{
public IArchive TestData {get; set;}
public IArchive Create()
{
return this.TestData;
}
}
Это вызывает некоторые изменения в вашем коде: вместо того, чтобы просто вызывать новый MyDbContext, вам придется попросить ArchiveFactory создать его.Кроме того, у каждого класса, который хочет использовать новый MyDbContext, должен быть один и тот же ArchiveFactory.
Однако, хотя это решение кажется довольно изящным, его реализация довольно сложна, и даже после того, как вы это сделаличто он по-прежнему будет иметь ограниченную функциональность, особенно если вы хотите добавить / удалить элементы и хотите использовать связи между таблицами.
Каждое изменение в отношениях между таблицами в вашей базе данных также приведет к изменению в вашем Архиве.Я бы пошел на фальшивую базу данных, как усилие, и использовал бы исходную функциональность платформы сущностей.