MsTest - макетирование DbContext с помощью DbContextOption и конфигурации
У меня есть 2 проекта, Data и Data.test, я использую ядро ef и ядро .net для них обоих, для проекта данных у меня есть ExpenseDb, например:
public class ExpenseDb: DbContext
{
private IConfigurationRoot _config;
public ExpenseDb(DbContextOptions<ExpenseDb> options, IConfigurationRoot config) : base(options)
{
_config = config;
}
public DbSet<Account> Accounts { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlServer(_config["Data:ConnectionString"]);
}
}
И у меня есть хранилище для учетной записи, как это:
private ExpenseDb _db;
public AccountRepository(ExpenseDb db)
{
_db = db;
}
public IEnumerable<Account> All(Guid userId)
{
return (_db.Accounts.AsNoTracking().Where(a => a.UserId == userId).ToList());
}
Я использую MS IOC для таких зависимостей:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json");
_config = builder.Build();
}
IConfigurationRoot _config;
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(_config);
services.AddDbContext<ExpenseDb>(ServiceLifetime.Scoped);
}
Все они находятся в моем проекте Data, и для Data.Test я хотел бы протестировать метод All, я понял, что должен смоделировать свой ExpenseDb, поэтому я получил Moq из пакета Nuget, и теперь у меня есть такой тестовый класс:
[TestClass]
public class AccountRepositoryTest
{
private readonly Mock<ExpenseDb> _dbMock = new Mock<ExpenseDb>();
private readonly AccountRepository _repo;
public AccountRepositoryTest()
{
_repo = new AccountRepository(_dbMock.Object);
}
[TestMethod]
public void AllForInvalidUser()
{
var fakeaccount = new Account() { Name="cat2",OpenDate=DateTime.Now,StartBalance=100};
Mock < DbSet < Account >> acMock = DbSetMock.Create(fakeaccount);
var results = _repo.All(Guid.Parse("cf15c6c9-f688-47ee-892e-297e530be053"));
Assert.IsNotNull(results);
}
}
Очевидно, мой тест не пройден, потому что я должен как-то передать конфигурацию и параметры в ExpenseDb, но я не знаю, как?!
Я искал и обнаружил, что все ответы говорят: "У вас должен быть интерфейс для вашего сервиса", но я не хочу создавать ненужный интерфейс.
1 ответ
Поскольку DbContextOptions и config не используются в реальном тестовом коде. Вы можете создать конструктор в своем контексте базы данных, помеченный как защищенный, чтобы разрешить создание экземпляра объекта ExpenseDb без каких-либо параметров.