1

我刚刚在我的应用程序中遇到了一个错误,可能已经被一些集成测试捕获了,所以我认为是时候写一些了!

我的问题与这些测试的设置有关,以及您在代码的哪一层运行测试。

设置

考虑到我应该有很多集成测试,我不想为每个测试创建和删除一个测试数据库,这会非常慢(即使它是内存中的 SqlLite)。我的想法是:

  1. 在我的开发数据库旁边有一个测试数据库
  2. 在测试之前,运行一些重置脚本,它将正确设置我的模式并插入任何必要的数据(不是特定于测试用例)
  3. 只需使用这个测试数据库,就好像它是真正的数据库一样。

但是,我必须在每个 [Setup] 中运行我的 Fluent NHib 配置似乎非常浪费。这很难吗?我在这里有什么选择?

我的会话当前包含在 UoW 模式中,分别在 begin_request 和 end_request(MVC Web 应用程序)上执行创建和销毁。我应该修改它以与测试一起解决这个问题吗?

测试

在实际编写一些测试时,我应该怎么做?

我应该从可能的最高级别(我的 MVC 控制器操作)还是从最低级别(存储库)进行测试。

如果我测试最低,我将不得不手动对所有数据进行硬编码。这将使我的测试对代码的更改变得脆弱,并且也不能代表运行时代码中实际发生的情况。如果我在最高级别进行测试,我必须运行我的所有 IoCC 设置,以便注入依赖项并让整个事情发挥作用(再次,在每个 [SetUp] 中重复这个?)

呸!我迷路了,有人指出我正确的方向!

谢谢

4

2 回答 2

2

In regards to creating the session factory, I create a class called _AssemblyCommon in my test project and expose the session factory as a static from there. A method marked with the [SetupFixture] (NUnit) attribute configures the session factory.

In general integration tests should cover CRUD operations in the repositories. To do this, I have one test method per object (or aggregate root) and do an insert, retrieve, update, and delete all within that method. I also test any cascade deletes that I've defined. Keeping these operations in a single method doesn't leave any traces behind in the database. I do have some integration tests that leave behind test data but that hasn't been a problem.

Your higher level operations should be unit tested and mock (I use Moq) the repositories if possible.

于 2009-04-17T12:12:22.917 回答
1

在我当前的 MVC 应用程序中,我发现测试存储库和数据库之间的交互就足够了。最重要的是,这是为了消除 NHibernate 映射中的任何皱纹。该层之上的所有内容(好吧,当我说所有内容时我都在夸大其词)都是单独进行单元测试的。我确实有一些从控制器一直到堆栈到数据库的集成测试,这些测试使用 IoC 容器 (StructureMap) 来构建控制器和依赖项,但我发现这些测试实际上并没有添加任何东西,而且它们相当维护的开销,所以我现在已经从“集成”测试中删除了它们——我可能会找到一个理由把它们放进去,但到目前为止我还没有。

无论如何,我使用的测试过程是这样的:

数据访问层测试程序集的构建过程通过 FluentNHibernate 配置 ExposeSchema() 调用创建测试数据库。构建过程然后运行一些 NHibernate 存储库级别的代码来填充数据库中的引用表。

然后将运行的每个集成测试包装在 System.Transactions.TransactionScope using() 语句中,并且 TransactionScope 永远不会调用 Complete(),因此每个测试都可以单独运行,并且可以在 using() 范围内设置和验证结果通过 ISession 而不改变任何其他测试数据的状态。例如

  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 实现 - 事务在更高级别回滚。

于 2009-04-17T12:59:31.023 回答