使用 Repository 和 UnitOfWork 模拟删除
Mocking A Delete using Repository and UnitOfWork
使用 Unit
,我正在尝试设置一个测试,我可以从我的 Mock
列表中删除一个条目,以便测试我的 CustomerManager
中的实现。
我的资料库:
public class Repository<T> : IRepository<T> where T : ModelBase
{
private readonly CustomerDbContext _context;
public Repository(CustomerDbContext context)
{
if (_context == null)
throw new ArgumentNullException(nameof(context));
_context = context;
}
public async Task Delete(int id, bool softDelete = true)
{
var entity = await GetById(id);
if (entity == null) return;
if (softDelete)
{
entity.IsDeleted = true;
Save(entity);
}
else
_context.Set<T>().Remove(entity);
}
public async Task<T> GetById(int id)
{
return await _context.Set<T>().FirstOrDefaultAsync(t => t.Id == id).ConfigureAwait(false);
}
public void Save(T entity)
{
if (entity.Id == 0)
_context.Set<T>().Add(entity);
else
_context.Entry(entity).State = EntityState.Modified;
}
}
我的工作单位是:
public class CustomerUnitOfWork : IUnitOfWork
{
public CustomerDbContext Context { get; }
public async Task<int> Commit()
{
foreach(var item in Context.ChangeTracker.Entries().Where(e => e.State == EntityState.Added || e.State == EntityState.Modified))
{
if (!(item.Entity is ModelBase entity))
continue;
if (item.State == EntityState.Added)
{
entity.CreatedDate = DateTime.UtcNow;
}
entity.ModifiedDate = DateTime.UtcNow;
}
return await Context.SaveChangesAsync();
}
}
我的经理是:
public class CustomerManager : ICustomerManager
{
private readonly IRepository<Models.Customer> _customerRepository;
protected readonly IUnitOfWork _unitOfWork;
public CustomerManager(IRepository<Models.Customer> customerRepository, IUnitOfWork unitOfWork)
{
_customerRepository = customerRepository;
_unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
}
public async Task<int> Delete(int id, bool softDelete = true)
{
await _customerRepository.Delete(id, softDelete);
return await _unitOfWork.Commit();
}
public async Task<Models.Customer> GetById(int id)
{
return await _customerRepository.GetById(id);
}
}
在我的单元测试中,我像这样设置构造函数:
private ICustomerManager MockManager;
private Mock<IUnitOfWork> UnitOfWork;
private List<Models.Customer> Customers;
Mock<IRepository<Models.Customer>> MockRepository;
public CustomerTest()
{
MockRepository = new Mock<IRepository<Models.Customer>>();
UnitOfWork = new Mock<IUnitOfWork>();
Customers = new List<Models.Customer>()
{
new Models.Customer
{
Id = 1,
Name = "Foo",
City = "Baltimore",
Company = "Foo Company"
},
new Models.Customer
{
Id = 2,
Name = "Bar",
City = "Owings Mills",
Company = "Bar Company"
}
};
MockRepository.Setup(repo => repo.GetAll()).ReturnsAsync(Customers);
MockRepository.Setup(repo => repo.GetById(It.IsAny<int>())).ReturnsAsync((int i) => Customers.SingleOrDefault(c => c.Id == i));
MockRepository.SetupAllProperties();
MockManager = new CustomerManager(MockRepository.Object, UnitOfWork.Object);
}
在我的测试方法中,我想删除测试列表中的第一个对象。
public async Task ShouldDelete()
{
var countBeforeDelete = Customers.Count();
var countAfterDelete = await MockManager.Delete(1, true);
Assert.Equal(countBeforeDelete, countAfterDelete);
}
但是,CountAfterDelete
总是returns0。我不确定我做错了什么。
您经理的 Delete
方法 returns await _unitOfWork.Commit();
默认情况下,IUnitOfWork
的 Mock 将 return default(int) 为 0。
使用 Unit
,我正在尝试设置一个测试,我可以从我的 Mock
列表中删除一个条目,以便测试我的 CustomerManager
中的实现。
我的资料库:
public class Repository<T> : IRepository<T> where T : ModelBase
{
private readonly CustomerDbContext _context;
public Repository(CustomerDbContext context)
{
if (_context == null)
throw new ArgumentNullException(nameof(context));
_context = context;
}
public async Task Delete(int id, bool softDelete = true)
{
var entity = await GetById(id);
if (entity == null) return;
if (softDelete)
{
entity.IsDeleted = true;
Save(entity);
}
else
_context.Set<T>().Remove(entity);
}
public async Task<T> GetById(int id)
{
return await _context.Set<T>().FirstOrDefaultAsync(t => t.Id == id).ConfigureAwait(false);
}
public void Save(T entity)
{
if (entity.Id == 0)
_context.Set<T>().Add(entity);
else
_context.Entry(entity).State = EntityState.Modified;
}
}
我的工作单位是:
public class CustomerUnitOfWork : IUnitOfWork
{
public CustomerDbContext Context { get; }
public async Task<int> Commit()
{
foreach(var item in Context.ChangeTracker.Entries().Where(e => e.State == EntityState.Added || e.State == EntityState.Modified))
{
if (!(item.Entity is ModelBase entity))
continue;
if (item.State == EntityState.Added)
{
entity.CreatedDate = DateTime.UtcNow;
}
entity.ModifiedDate = DateTime.UtcNow;
}
return await Context.SaveChangesAsync();
}
}
我的经理是:
public class CustomerManager : ICustomerManager
{
private readonly IRepository<Models.Customer> _customerRepository;
protected readonly IUnitOfWork _unitOfWork;
public CustomerManager(IRepository<Models.Customer> customerRepository, IUnitOfWork unitOfWork)
{
_customerRepository = customerRepository;
_unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
}
public async Task<int> Delete(int id, bool softDelete = true)
{
await _customerRepository.Delete(id, softDelete);
return await _unitOfWork.Commit();
}
public async Task<Models.Customer> GetById(int id)
{
return await _customerRepository.GetById(id);
}
}
在我的单元测试中,我像这样设置构造函数:
private ICustomerManager MockManager;
private Mock<IUnitOfWork> UnitOfWork;
private List<Models.Customer> Customers;
Mock<IRepository<Models.Customer>> MockRepository;
public CustomerTest()
{
MockRepository = new Mock<IRepository<Models.Customer>>();
UnitOfWork = new Mock<IUnitOfWork>();
Customers = new List<Models.Customer>()
{
new Models.Customer
{
Id = 1,
Name = "Foo",
City = "Baltimore",
Company = "Foo Company"
},
new Models.Customer
{
Id = 2,
Name = "Bar",
City = "Owings Mills",
Company = "Bar Company"
}
};
MockRepository.Setup(repo => repo.GetAll()).ReturnsAsync(Customers);
MockRepository.Setup(repo => repo.GetById(It.IsAny<int>())).ReturnsAsync((int i) => Customers.SingleOrDefault(c => c.Id == i));
MockRepository.SetupAllProperties();
MockManager = new CustomerManager(MockRepository.Object, UnitOfWork.Object);
}
在我的测试方法中,我想删除测试列表中的第一个对象。
public async Task ShouldDelete()
{
var countBeforeDelete = Customers.Count();
var countAfterDelete = await MockManager.Delete(1, true);
Assert.Equal(countBeforeDelete, countAfterDelete);
}
但是,CountAfterDelete
总是returns0。我不确定我做错了什么。
您经理的 Delete
方法 returns await _unitOfWork.Commit();
默认情况下,IUnitOfWork
的 Mock 将 return default(int) 为 0。