EF4代码第一,TDD,CRUD和事务 [英] EF4 Code First, TDD, CRUD, and Transactions
问题描述
过去,在创建数据访问/存储库代码时,我已经为简单的CRUD操作编写了单元测试:
In the past, I've written unit tests for simple CRUD operations when creating data access/repository code that look something like this:
using(var connection = new WhateverConnection(connectionString))
{
connection.Open();
using(var transaction = connection.BeginTransaction())
{
try
{
//test the CRUD operation
}
finally
{
//gets rid of any stuff created during the test
transaction.Rollback();
}
}
}
我正在搞乱EF4代码首先今天,我意识到我不知道这个测试场景如何在实体框架词典中翻译。看来,如果我调用 DbContext.SaveChanges()
,它会保存和提交,而不管 AcceptAllChanges ()
被调用。即使使用 ObjectContext
而不是 DbContext
,我无法确定如何在不手动清除的情况下重新创建这个简单的测试场景创建任何模拟/测试对象。我已经阅读了 MSDN上的这篇文章,但是 / code>还没有一个
回滚
类型方法。我使用 TransactionScope
,从不调用完成
?在单元测试期间是否有另一种使用DbContext和/或ObjectContext的方法或方式进行回滚?我需要用EF4 Code First完全重新调整我的TDD思维吗?
I was messing around with EF4 Code First today, and I realized that I have no idea how this testing scenario translates in the Entity Framework lexicon. It seems that, if I call DbContext.SaveChanges()
, it saves and commits, regardless of whether or not AcceptAllChanges()
was called. Even using ObjectContext
instead of DbContext
, I can't figure out how this simple test scenario can be recreated without manually cleaning up any mock/test objects created. I did read this article on MSDN, but TransactionScope
doesn't really have a Rollback
type method either. Do I use TransactionScope
and never call Complete
? Is there another method or manner of using DbContext and/or ObjectContext in order to Rollback during unit tests? Do I need to completely re-adjust my thinking for TDD with EF4 Code First?
推荐答案
ObjectContext
本身不会暴露事务行为。你自己必须在交易中包装EF代码。简单的方法是使用 TransactionScope
。如果您不调用范围上的完成
方法并处理它,它将执行回滚。我们通常使用基类进行这种集成测试:
ObjectContext
itself does not expose transactional behavior. You have to wrap EF code in transaction by yourself. The easy way to do it is using TransactionScope
. If you don't call Complete
method on the scope and dispose it, it will perform rollback. We are usually using base class for this type of integration tests:
[TestClass]
public abstract class TransactionTestBase
{
private TransactionScope scope = null;
[TestInitialize]
public virtual void TestInitialize()
{
scope = new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadUncommitted
});
}
[TestCleanup]
public virtual void TestCleanup()
{
if (scope != null)
{
scope.Dispose();
scope = null;
}
}
}
所有测试类派生自类。 TestInitialize
在派生类中的每个 TestMethod
之前调用, TestCleanup
在每个 TestMethod
后调用,所以您的测试根本不需要处理交易。
All test classes derive from this class. TestInitialize
is called before each TestMethod
in derived class and TestCleanup
is called after each TestMethod
so your tests don't have to deal with transaction at all.
这篇关于EF4代码第一,TDD,CRUD和事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!