我正在学习单元测试,并有一个问题。
我用我的数据模拟了我的类ApplicationDbContext。
现在我想从我的数据中删除一个项目。 :(
第一次测试通过,但第二次测试失败,它仍然显示了20个项目
任何人都可以帮助我吗?
我的classe IApplicationDbContext:
public interface IApplicationDbContext : IDisposable
{
IDbSet<OrderingEquipment> OrderingEquipments { get; set; }
int SaveChanges();
Task<int> SaveChangesAsync();
}
我的classe ApplicationDbContext:
public class ApplicationDbContext : DbContext, IApplicationDbContext
{
public virtual IDbSet<OrderingEquipment> OrderingEquipments { get; set; }
public ApplicationDbContext() : base("DefaultConnection")
{
}
}
我的classe OrderingEquipment:
public class OrderingEquipment
{
[Key]
public Guid Guid { get; set; }
public string Text { get; set; }
public byte?[] xDEHFile { get; set; }
public string xDEHFileName { get; set; }
public DateTime Timestamp { get; set; }
public string ModelToString()
{
return string.Format("Guid: {0}, Text: {1}, xDEHFile: {2}, xDEHFileName: {3} Timestamp: {4}", Guid, Text, xDEHFile, xDEHFileName, Timestamp);
}
}
My Controller Methode:
public void Remove(OrderingEquipment orderingEquipments)
{
if (orderingEquipments == null)
{
//throw exception oder ein Result?
throw new ArgumentNullException("orderingEquipmentsCointener is null");
}
try
{
using (db)
{
//orderingEquipments.ForEach(x => log.Error("Removed: " + x.ModelToString()));
var itemToRemove = db.OrderingEquipments.Find(orderingEquipments.Guid);
db.OrderingEquipments.Remove(itemToRemove);
db.SaveChanges();
}
}
catch (Exception e)
{
// orderingEquipments.ForEach(x => log.Error(x.ModelToString(), e));
}
}
我的单元测试
public class OrderingEquipmentControllerTests
{
private IDbSet<OrderingEquipment> dbSet;
private IApplicationDbContext dbContext;
private OrderingEquipmentController controller;
[SetUp]
public void Initialize()
{
// Create test product data
var orderingEquipments = Builder<OrderingEquipment>.CreateListOfSize(20)
.All()
.With(p => p.Guid = Guid.NewGuid())
.With(p => p.Timestamp = DateTime.UtcNow.AddMonths(new Random().Next(1)))
.With(p => p.Timestamp = DateTime.UtcNow.AddDays(new Random().Next(2)))
.TheFirst(5)
.With(p => p.Text = "First five")
.Build()
.AsQueryable();
dbSet = Substitute.For<IDbSet<OrderingEquipment>>();
dbSet.Provider.Returns(orderingEquipments.Provider);
dbSet.Expression.Returns(orderingEquipments.Expression);
dbSet.ElementType.Returns(orderingEquipments.ElementType);
dbSet.GetEnumerator().Returns(orderingEquipments.GetEnumerator());
dbSet.Find(Arg.Any<object[]>()).Returns(callinfo =>
{
object[] idValues = callinfo.Arg<object[]>();
if (idValues != null && idValues.Length == 1)
{
Guid requestedId = (Guid)idValues[0];
return orderingEquipments.FirstOrDefault(p => p.Guid == requestedId);
}
return null;
});
dbContext = Substitute.For<IApplicationDbContext>();
dbContext.OrderingEquipments.Returns(dbSet);
controller = new OrderingEquipmentController(dbContext);
}
[Test()]
public void GetAllOrderingEquipmentsTest()
{
var items = controller.GetAllOrderingEquipments();
Assert.That(items.Count, Is.EqualTo(20));
}
[Test()]
public void RemoveOneOrderingEquipment()
{
var items = controller.GetAllOrderingEquipments();
controller.Remove(items.First());
Assert.That(items.Count, Is.EqualTo(19));
}
}
答案 0 :(得分:0)
模拟的数据库由用于查询的虚假数据存储支持。它实际上并没有保存任何添加到它的东西。您还必须设置模拟在从中删除项目时的假设。
// Create test product data
var orderingEquipments = Builder<OrderingEquipment>.CreateListOfSize(20)
.All()
.With(p => p.Guid = Guid.NewGuid())
.With(p => p.Timestamp = DateTime.UtcNow.AddMonths(new Random().Next(1)))
.With(p => p.Timestamp = DateTime.UtcNow.AddDays(new Random().Next(2)))
.TheFirst(5)
.With(p => p.Text = "First five")
.Build()
.ToList();
var queryable = orderingEquipments.AsQueryable();
dbSet = Substitute.For<IDbSet<OrderingEquipment>>();
dbSet.Provider.Returns(queryable.Provider);
dbSet.Expression.Returns(queryable.Expression);
dbSet.ElementType.Returns(queryable.ElementType);
dbSet.GetEnumerator().Returns(queryable.GetEnumerator());
dbSet.Find(Arg.Any<object[]>()).Returns(callinfo => {
object[] idValues = callinfo.Arg<object[]>();
if (idValues != null && idValues.Length == 1) {
Guid requestedId = (Guid)idValues[0];
return queryable.FirstOrDefault(p => p.Guid == requestedId);
}
return null;
});
//Setup remove on db set to remove actual item from fake collection
dbSet.Remove(Arg.Any<OrderingEquipment>())
.Returns(callInfo => {
var item = callInfo.Arg<OrderingEquipment>();
return item != null && orderingEquipments.Remove(item);
});
这样,模拟的dbSet将知道在要求删除项目时如何表现。测试时模拟使用的任何成员都必须配置为按预期运行。
除此之外,我必须说你不应该嘲笑你不拥有的代码。 DbSet不需要测试。 MS会在发布之前测试它。您也不必直接在控制器中使用它。摘要并将抽象注入控制器。在维护和测试代码时可以提供更大的灵活性。