在我的项目中,我遵循Repository Pattern。我的存储库与持久层对话,我使用实体框架作为ORM。
目前,在我的单元测试中,我直接针对持久层进行编码,因此任何测试都直接针对数据库运行。因此,如果我测试插入,它实际上会将数据插入数据库。
我想知道如何测试而不必担心数据库被修改?
我有办法进行内存数据库测试吗?
由于
我在App_Data中创建了一个类似于实际的数据库模式,然后我尝试像这样实现它 -
[TestInitialize]
public void TestInitialize()
{
//TODO: in TestCleanup, do a rollback to revert any changes performed during the test.
Database.SetInitializer<LogViewerDbContextFake>(new LogViewerInitializer());
}
[TestMethod]
public void Get_Should_Return_List_Of_Applications()
{
// Arrange
LogViewerDbContext testDbContext = new LogViewerDbContextFake();
ApplicationRepository sut = new ApplicationRepositoryImpl(testDbContext);
// Act
List<string> failure = sut.Get();
// Assert
Assert.AreEqual(4, failure.Count);
}
internal class LogViewerInitializer : DropCreateDatabaseIfModelChanges<LogViewerDbContextFake>
{
protected override void Seed(LogViewerDbContextFake context)
{
List<LogEntry> logEntries = new List<LogEntry>()
{
new LogEntry{
Id = 1,
Application = "Application 1"
},
new LogEntry{
Id = 2,
Application = "Application 2"
},
new LogEntry{
Id = 3,
Application = "Application 3"
},
new LogEntry{
Id = 4,
Application = "Application 4"
},
new LogEntry{
Id = 5,
Application = "Application 2"
},
new LogEntry{
Id = 6,
Application = "Application 2"
}
};
logEntries.ForEach(s => context.LogEntries.Add(s));
context.SaveChanges();
}
}
即使测试运行并通过,LogViewerInitializer也没有在App_Data \ Database中插入任何记录。所以,我想知道背后的逻辑是什么以及事情究竟是如何被执行的?
答案 0 :(得分:1)
使用TransactionScope块来避免将数据提交到数据库。
using (TransactionScope scope = new TransactionScope())
{
// test goes here
db.SaveChanges();
// assertions
}
答案 1 :(得分:0)
您是否尝试过使用像Rhinomocks或MOQ这样的模拟框架来模拟持久层?
或者,您可以提出您实际上正在进行端到端测试的参数,并在运行测试后从数据库中删除数据。您可以通过在使用属性运行测试之前和之后运行post和pre sql脚本来完成此操作。如果您使用的是PostSharp等AOP框架,这将非常简单。如果没有,你仍然可以使用contextbound对象来完成它,正如我已经解释过here
答案 2 :(得分:0)
我使用ninject和EF构建了自己的存储库框架。如果您有兴趣,请看一下这里,我还有一个如何使用我的存储库框架来生成简单单元测试的示例。
http://blog.staticvoid.co.nz/2011/10/staticvoid-repository-pattern-nuget.html