我刚刚在我的应用程序中遇到一个可能已经被某些集成测试捕获的错误,所以我认为我写这篇文章的时间很长!
我的问题涉及这些测试的设置,以及您运行测试的代码层。
设置
考虑到我应该进行大量的集成测试,我不想为每个测试创建和删除测试数据库,这将是非常慢的(即使它是一个SqlLite内存中的)。我的想法是:
然而,在每个[Setup]中运行我的Fluent NHib配置似乎非常浪费。这真的很难吗?我有什么选择?
我的会话当前包含在UoW模式中,分别在begin_request和end_request(MVC Web应用程序)上执行创建和销毁。我应该修改它以便与测试一起解决这个问题吗?
测试
当谈到实际编写一些测试时,我应该怎么做?
我应该从最高级别(我的MVC控制器操作)还是从最低级别(存储库)进行测试。
如果我在最低处测试,我将不得不手动硬编码所有数据。这将使我的测试对代码中的更改变得脆弱,也无法代表运行时代码中真正发生的情况。如果我在最高级别进行测试,我必须运行所有IoCC设置,以便注入依赖关系并完成所有功能(再次,在每个[SetUp]中重复一次?)
咩!我迷路了,有人指着我正确的方向!
由于
答案 0 :(得分:2)
关于创建会话工厂,我在我的测试项目中创建了一个名为_AssemblyCommon的类,并从那里将会话工厂公开为静态。标有[SetupFixture](NUnit)属性的方法配置会话工厂。
通常,集成测试应涵盖存储库中的CRUD操作。为此,我为每个对象(或聚合根)提供了一个测试方法,并在该方法中执行插入,检索,更新和删除操作。我还测试了我定义的任何级联删除。将这些操作保存在单个方法中不会在数据库中留下任何痕迹。我确实有一些集成测试会留下测试数据,但这不是问题。
如果可能,您的更高级别操作应进行单元测试并模拟(我使用Moq)存储库。
答案 1 :(得分:1)
在我目前的MVC应用程序中,我发现它足以测试存储库和数据库之间的交互。最重要的是,这可以消除NHibernate映射中的任何皱纹。在该层之上的所有东西(当我说出所有内容时我都夸大其词)都是单独进行单元测试的。我确实从控制器一直到堆栈到数据库进行了一些集成测试,这些测试使用了IoC容器(StructureMap)来构建控制器和依赖项,但我发现这些测试实际上并没有添加任何内容,而且它们非常相似维护的开销,所以我暂时将它们从“集成”测试中删除了 - 我可能会找到理由将它们放入,但到目前为止我还没有。
无论如何,我使用的测试过程是这样的:
数据访问层测试程序集的构建过程通过FluentNHibernate配置ExposeSchema()调用创建测试数据库。然后构建过程运行一些NHibernate存储库级代码来填充数据库中的引用表。
然后运行的每个集成测试都包含在System.Transactions.TransactionScope using()语句中,并且TransactionScope永远不会调用Complete(),因此每个测试都可以独立运行,并且可以在使用中设置和验证结果()范围由ISession而不改变任何其他测试数据的状态。 e.g。
using (new TransactionScope())
{
var session = NHibernateTestSessionCreator.GetNHibernateSessionForIntegrationTesting();
// This is an NHibernate ISession - setup any dependencies for the repository tests here
var testRepository = new NHibernateGenericRepository<NewsItem>(NHibernateTestSessionCreator.GetNHibernateSessionForIntegrationTesting())
// repository test code goes here - the repository is using a different ISession
// Validate the results here directly with the ISession
}
// at this point the transaction is rolled back and we haven't changed the test data
这意味着我不必修改我正在使用的UnitOfWork实现 - 事务在更高级别回滚。