我目前的代码如下:
[TestClass]
public class TestClass
{
private const string ConnectionString = "...";
private const string TemplateDatabaseBackupPath = "...";
[ClassInitialize]
public static void ClassInitialize(TestContext context) {
InitializeTestEnviroment(); // create & fill db, init internals
using (SqlConnection connection = new SqlConnection(ConnectionString)) {
connection.Open();
using (SqlCommand command = connection.CreateCommand()) {
command.CommandText = "BACKUP DATABASE [Testing] TO DISK = @path";
command.Parameters.AddWithValue("path", TemplateDatabaseBackupPath);
command.ExecuteNonQuery();
}
}
}
[TestCleanup]
public static void TestCleanup() {
using (SqlConnection connection = new SqlConnection(ConnectionString)) {
connection.Open();
using (SqlCommand command = connection.CreateCommand()) {
command.CommandText = "ALTER DATABASE [Testing] SET SINGLE_USER WITH ROLLBACK IMMEDIATE";
command.ExecuteNonQuery();
}
using (SqlCommand command = connection.CreateCommand()) {
command.CommandText = @"RESTORE DATABASE [Testing] FROM DISK = @path WITH REPLACE";
command.Parameters.AddWithValue("path", TemplateDatabaseBackupPath);
command.ExecuteNonQuery();
}
}
}
[TestMethod]
public void TestMethod() {
Entity entity = new Entity { Name = "Fred Flindstone" };
BlackBox.UpdateEntity(entity, 42);
Entity actual = BlackBox.GetEntityById(42);
Assert.AreEqual("Fred Flindstone", actual.Name);
}
[TestMethod]
public void TestMethod2() {
Entity entity = new Entity { Name = "Fred Flindstone" };
BlackBox.UpdateEntity(entity, 42); // 42 = entity id
Entity actual = BlackBox.GetEntityById(42);
Assert.AreEqual("Fred Flindstone", actual.Name);
}
}
// NH mapping class
public class Entity {
public int Id;
public string Name;
}
// Not real code - just to get the idea how CRUD are performed internally, this code cannot be easily changed (no unit tests for it)
public static class BlackBox {
public static void UpdateEntity(object entity, int id) {
using(var s = GetSession()){
s.Update(id, entity);
}
}
public static void GetEntityById(int id) {
using(var s = GetSession()){
return s.Session.Query<Entity>().Single(o => o.Id == Id);
}
}
private static IHiberSession GetSession(){
return ...; // not relevant
}
public interface IHiberSession {
ISession Session { get; }
...
}
}
经过一些调查后我发现了这个:
ClassInitialize 8s
TestMethod and TestMethod2 ~20ms
TestCleanup 3s
显然我想减少TestCleanup的时间......
经过一番搜索,我找到了System.Transactions.TransactionScope并认为我有一个胜利者:[ClassInitialize]
public static void ClassInitialize(TestContext context) {
InitializeTestEnviroment();
}
[TestInitialize]
public static void TestInitialize() {
_Scope = new System.Transactions.TransactionScope();
}
[TestCleanup]
public static void TestCleanup() {
_Scope.Dispose(); // Rollback any changes made by test
}
应该比数据库恢复更快但不幸的是 我在会话Close()方法
期间得到此异常System.InvalidOperationException: Disconnect cannot be called while a transaction is in progress.
似乎与这个封闭的问题有关:NH-1744但是这不会给我任何想法,请修改我的代码:(
无论如何,我的问题是如何让这段代码起作用:
void TestMethod() {
using(var scope = new System.Transactions.TransactionScope()) {
// these two usings cannot be changed ...
using (ISession session = GetSession()) {
// some CRUD
}
using (ISession session = GetSession()) {
// some more CRUD
}
}
}
或任何其他想法,如何使数据库快速备份/恢复? (内存中备份会很好)
PS:TransactionScope仅用于单元测试,&#39; live&#39;代码是无范围的
感谢您的帮助......