Ответ 1
public class AppContext : DbContext
{
public AppContext()
{
Configuration.LazyLoadingEnabled = true;
}
public virtual DbSet<AccountType> AccountTypes { get; set; }
}
public class AccountType
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<AccountCode> AccountCodes { get; set; }
}
public class AccountCode
{
public Guid Id { get; set; }
public string Name { get; set; }
public Guid AccountTypeId { get; set; }
public virtual AccountType AccountType { get; set; }
}
Виртуальное ключевое слово в свойствах навигации используется для включения ленивого механизма загрузки, но свойство LazyLoadingEnabled конфигурации должно быть включено.
Виртуальное ключевое слово в свойстве AccountType:: AccountCodes будет загружать все коды учетной записи в тот момент, когда есть программный доступ к этому свойству, в то время как контекст db все еще жив.
using (var context = new AppContext())
{
var accountType = context.AccountTypes.FirstOrDefault();
var accountCodes = accountType.AccountCodes;
}
В то время как ключевое слово virtual на производном классе DbContext (виртуальный DbSet < > ) используется для целей тестирования (издеваясь над свойством DbSet), виртуальное ключевое слово в этом случае не связано с ленивой загрузкой.
===== update =====
Обычно мы проводим тестирование против службы/логики, например, у нас есть другой уровень для службы типа учетной записи, как показано ниже. И служба принимает экземпляр контекста db, используя какую-либо инъекцию зависимостей через конструктор.
public class AccountTypeService
{
public AppContext _context;
public AccountTypeService(AppContext context)
{
_context = context;
}
public AccountType AddAccountType(string name)
{
var accountType = new AccountType { Id = Guid.NewGuid(), Name = name };
_context.AccountTypes.Add(accountType);
_context.SaveChanges();
return accountType;
}
}
И теперь нам нужно проверить службу типа учетной записи, в этом случае я использовал mstest и automoq для создания класса mock.
[TestClass]
public class AccountTypeServiceTest
{
[TestMethod]
public void AddAccountType_NormalTest()
{
// Arranges.
var accountTypes = new List<AccountType>();
var accountTypeSetMock = new Mock<DbSet<AccountType>>();
accountTypeSetMock.Setup(m => m.Add(It.IsAny<AccountType>())).Callback<AccountType>(accountType => accountTypes.Add(accountType));
var appContextMock = new Mock<AppContext>();
appContextMock.Setup(m => m.AccountTypes).Returns(accountTypeSetMock.Object);
var target = new AccountTypeService(appContextMock.Object);
// Acts.
var newAccountType = target.AddAccountType("test");
// Asserts.
accountTypeSetMock.Verify(m => m.Add(It.IsAny<AccountType>()), Times.Once());
appContextMock.Verify(m => m.SaveChanges(), Times.Once());
Assert.AreEqual(1, accountTypes.Count);
Assert.IsNotNull(newAccountType);
Assert.AreNotEqual(Guid.Empty, newAccountType.Id);
Assert.AreEqual("test", newAccountType.Name);
}
}