我有一个基础对象,它包含一个Version属性,标记为ConcurrencyCheck
public class EntityBase : IEntity, IConcurrencyEnabled
{
public int Id { get; set; }
[ConcurrencyCheck]
[Timestamp]
public byte[] Version { get; set; }
}
然而,这是有效的,我想编写测试以确保它不会被破坏。不幸的是,我似乎无法弄清楚如何编写一个不依赖于物理数据库的测试!
相关的测试代码有效,但使用数据库......
protected override void Arrange()
{
const string asUser = "ConcurrencyTest1"; // used to anchor and lookup this test record in the db
Context1 = new MyDbContext();
Context2 = new MyDbContext();
Repository1 = new Repository<FooBar>(Context1);
Repository2 = new Repository<FooBar>(Context2);
UnitOfWork1 = new UnitOfWork(Context1);
UnitOfWork2 = new UnitOfWork(Context2);
Sut = Repository1.Find(x => x.CreatedBy.Equals(asUser)).FirstOrDefault();
if (Sut == null)
{
Sut = new FooBar
{
Name = "Concurrency Test"
};
Repository1.Insert(Sut);
UnitOfWork1.SaveChanges(asUser);
}
ItemId = Sut.Id;
}
protected override void Act()
{
_action = () =>
{
var item1 = Repository1.FindById(ItemId);
var item2 = Repository2.FindById(ItemId);
item1.Name = string.Format("Changed @ {0}", DateTime.Now);
UnitOfWork1.SaveChanges("test1");
item2.Name = string.Format("Conflicting Change @ {0}", DateTime.Now);
UnitOfWork2.SaveChanges("test2"); //Should throw DbUpdateConcurrencyException
};
}
[TestMethod]
[ExpectedException(typeof(DbUpdateConcurrencyException))]
public void Assert()
{
_action();
}
如何删除数据库要求???
答案 0 :(得分:0)
我建议将MyDbContext解压缩到接口IMyDbContext
,然后创建一个TestDbContext类,它也会按照你的方式实现SaveChanges,除了返回一个随机值(如1)而不是实际保存到数据库。
那时你需要做的就是测试,事实上,所有实体的版本号都得到了提升。
或者您也可以执行示例found here或here。
编辑:我实际上刚刚找到了使用TimeStamp进行this blog post并发检查的直接示例。
答案 1 :(得分:0)
我认为你不应该试图模仿这种行为来启用“纯”单元测试。有两个原因:
它需要相当多的代码来模拟数据库行为:以具有版本值的方式实现对象,缓存原始对象(模拟存储),更新时修改版本值,比较版本值与原始版本值相同,在版本不同时抛出异常,可能更多。所有这些代码都可能受到错误的影响,更糟糕的是,可能与实际情况略有不同。
你将陷入循环推理:你专门为单元测试编写代码然后......你编写单元测试来测试这段代码。绿色测试表明一切正常,但不包括应用程序代码的基本部分。
这只是linq对很难(不可能)模拟的实体的众多方面之一。我正在编制这些差异的清单here。