【问题标题】:Unit test insert/update/delete单元测试插入/更新/删除
【发布时间】:2010-03-18 19:52:38
【问题描述】:

我用谷歌搜索了一下,并没有真正找到我需要的答案。

我正在为客户使用 SQL Server 和 LINQ 编写 C# 网页。 我希望用户能够互相发送消息。所以我要做的是用实际进入数据库的数据对此进行单元测试。

问题是我现在依赖于至少 2 个我知道其 ID 的用户。此外,我必须清理自己。这会导致相当大的单元测试在一个测试中进行大量测试。

假设我想更新一个用户。这意味着我必须先删除用户,更新它,然后再删除它。一个单元测试中有很多断言,如果更新失败,我必须手动删除它。

如果我以其他方式进行,而不将数据保存到数据库,我肯定无法知道更新等后数据是否存在于数据库中。

如果没有在一个测试中测试大量功能的测试,那么执行此操作的正确方法是什么?

【问题讨论】:

  • “所以我所做的就是用实时数据对此进行单元测试”这是矛盾的。实时数据意味着您不是在进行单元测试,而是在进行可用性测试或性能测试,或者可能是集成测试。单元测试意味着“自己测试很多功能”。也许您应该更新问题。
  • 感谢您指出这一点,我脑子里出了点问题。我现在编辑了

标签: c# asp.net sql-server linq unit-testing


【解决方案1】:

在 System.Transactions.TransactionScope 块内进行所有测试,并且根本不调用 Scope.Complete() ...所有更改将在您退出时回滚,其他用户将无法看到你在数据库中创建的临时数据,所以测试过程只会影响测试机..

您可以在 TransactionScope 的块中输入一个新用户,读取数据库以验证它是否输入正确,以及您需要检查的任何其他内容...

让单个单元测试方法模拟两个不同的用户,都在一个事务中......

例如代码

   using (var scop = new System.Transactions.TransactionScope())
   {
       // all your test code and Asserts that access the database, 
       // writes and reads, from any class, ...
       // to commit at the very end of this block,
       // you would call
       // scop.Complete();  // ..... but don't and all will be rolled back
   }

【讨论】:

  • 听起来像我需要的。这会像数据在数据库中一样工作,但我不会提交吗?我正在访问某些类中的数据,他们将不得不“认为”数据在数据库中
  • 其他用户可能能够看到它,如果他们使用事务隔离级别。不过,这通常是一种深思熟虑的行为,因此不必担心。
  • 这是怎么回事,数据是同时存入数据库还是存入内存?
  • 它使用本地(在客户端)分布式事务协调器,内置在 .Net 框架中,它使用两阶段提交,包括参与的资源提供者 MSSql 服务器)来管理提交本身。 .
  • @Kurresmack,只要您将其他类的代码包含在同一个“块”中(请参阅对我的回答的编辑),那么是的,它们都会“看到”数据。
【解决方案2】:

有一个固定文件(XML、SQL、YAML 等),您只需一个命令即可将其加载到本地测试数据库中。

例如需要互相发送消息的两个用户的固定文件可能看起来像(这是我的):

Member:

  Member_WibWobble:
    username:       Wibble_Wobble
    email_address:  michael+dev_wibwob@[removed].com
    password:       pw
    is_super_admin: true
    last_login:     "2010-01-06 12:12:57"
    Country:        country_AU
    UploadImage:
      type:         <?php echo UploadImage::TYPE_MEMBER_AVATAR."\n"; ?>
      upload:       "http://localhost/[removed]/images/wibwobble.jpg"

  Member_BunnyHugs:
    username:       BunnyHugs
    email_address:  michael+dev_bunny@[removed].com
    password:       pw
    is_super_admin: true
    last_login:     "2009-12-01 14:11:11"
    Country:        country_UK
    UploadImage:
      type:         <?php echo UploadImage::TYPE_MEMBER_AVATAR."\n"; ?>
      upload:       "http://localhost/[removed]/images/bunnyhugs.jpg"

PrivateMessage:

  PrivateMessage_1:
    subject:          "Yo"
    body:         |
      hi

      <b>escape this html please</b>

      bye
    is_read:          false
    Sender:           Member_WibWobble
    Recipient:        Member_BunnyHugs

【讨论】:

  • 这是个好主意,尤其是当您在另一个基于内存的数据库上使用 SQLite 时。这将为您提供更好的性能,尤其是在您想使用大量数据进行测试时。
  • 但这是否意味着我必须将这些数据添加到数据库中才能对其进行测试..?
  • 是的,但是对于此类事情,您将拥有一个与生产数据库并行的相同模式测试数据库。
【解决方案3】:

单元测试数据库可以是 PITA,因为它们的本质(持久存储)。

要正确执行此操作,您应该始终从空白架构开始。然后让您的测试代码加载填写必须存在的数据值。这可以像执行一个包含架构和默认数据的 sql 脚本一样简单。

完成后,开始运行您的测试。测试应涵盖您的应用通常会执行的所有 crud 操作。

如果发生任何故障,这没什么大不了的,因为无论如何,您应该每次都重新开始。

此外,您希望在测试失败时保留该数据,以便您可以检查发生故障时的数据库状态。所以,这既是好事也是坏事。

按照这些思路,数据库测试应该在它自己的测试数据库实例上运行。这样您就不必担心在测试进行时有人更改您下方的数据库结构等临时问题。

归根结底,数据库测试本身就是一个项目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-05
    • 1970-01-01
    • 2014-08-27
    • 1970-01-01
    • 2018-12-19
    • 2011-12-11
    相关资源
    最近更新 更多