gpt4 book ai didi

sql-server - MSTest 单元测试 (VS 2012) 与 SQL Server,间歇性主键冲突

转载 作者:行者123 更新时间:2023-12-02 23:24:01 25 4
gpt4 key购买 nike

我正在处理一个非常奇怪的问题。最初,我认为这是清理测试数据的问题......但在完全重构我的测试数据清理代码后仍然看到完全相同的行为......我不知所措。

我在各个类中有 245 个单元测试方法。每个类都有自己唯一的测试数据,我初始化这些对象,然后在每个测试方法中,通常将数据插入数据库,然后用测试进行操作。每个测试类都有一个 ClassCleanup 方法,用于清除数据库中的所有测试数据,并且 ClassCleanup 也在 TestInitialize 上运行,以确保在运行任何其他测试方法之前清除所有内容。

当我使用 VS 2012 测试资源管理器“全部运行”时,22 个测试失败。它们都因违反主键约束的一些变化而失败。这意味着,当他们为这些测试初始化​​数据时,数据并未从该类中的先前测试方法中清除。如果我重新运行所有测试,我每次都会遇到相同的测试失败。这是相当可重现的。无论我运行所有测试多少次。这些相同的 27 次测试因主键违规而失败。

然而,奇怪的是,如果我只重新运行那些失败的测试,只有 9 个测试失败。这也是可重现的,这意味着,无论我只运行这 27 个以前失败的测试多少次,14 个都会失败,其余的都会通过。这会继续,因为我只运行失败的测试,直到我达到没有任何测试失败的程度。还应该注意的是,如果我单独运行每个测试类,一切都会通过。

我知道这看起来如何。

“你显然没有清理你的测试数据。”如果是这种情况,那么无论如何我都会看到相同的测试在每次运行时都失败了。这 27 个测试每次运行都应该失败,而不仅仅是在我运行其他所有测试时。

“你不能在类之间有唯一的主键,并且东西没有被清理。”看上面。即使我在我的类(class)中重复了主键(我没有重复,因为我已经亲自三次检查了各个类中测试数据的主键的唯一性),因为这些测试不是在单独的线程上同时运行(已通过记录 ThreadId 进行了验证),任何给定测试的清理代码都会清除重复的数据,无论如何。

“您不能使用连接池。”不,其实我是。而且我已经使用 SQL Profiler 验证了这些请求肯定是池化的。此外,因为这些测试不是并行运行的,所以只有一个连接线程。

“你不应该使用连接池。”嗯,是的,我应该,因为底层代码库支持各种 Web 项目,但为了论证,我尝试在禁用连接池的情况下运行所有​​测试(在连接字符串中使用 Pooling=false),我得到了完全相同的结果。任何行为都没有改变。

“你本地的环境一定有问题。”我在其他同事的开发箱(偶然使用 SQL 2012)上运行这些测试也得到了相同的结果。这不是我的环境所独有的,甚至不是我的 SQL Server 版本所独有的。

“您应该尝试从命令行运行 mstest。”已经这样做了。结果一样。

如果有人遇到过这样的事情,请告诉我。我知道一定有一些简单的东西我遗漏了,因为这些类型的问题通常就是这种情况,但是我已经尽可能多地覆盖了试图解决这个问题的基础。

最佳答案

以下假设基于您的数据库处于完全恢复模式并且您在测试期间不执行任何恢复或其他技巧(例如分离/重新附加数据库等)。

这是一种相当乏味的方法来调查您的问题,但保证提供解决此问题所需的数据。

  • 对数据库进行完整备份 在开始测试套件之前执行此操作。我们将要恢复数据库,因此还要确保您有足够的磁盘空间来存储 2-3 个数据库文件的副本。
  • 创建 Sql Profiler 跟踪 对于事件,选择 RPC 启动/完成、sql 批处理启动/完成、Sql 语句启动/完成、SP 语句启动/完成、TM:* 完成、SQLTransaction、DTCTransaction 和用户错误消息。捕获所有列。
  • 重现问题 运行最少数量的测试以产生故障。让测试完成以便您捕获所有清理代码,然后停止分析器跟踪。
  • 进行事务日志备份 稍后我们可能需要它来进行时间点恢复。
  • 在跟踪中定位故障 如果您遇到主键故障,那么应该很容易追踪,只需查找用户错误消息即可。记下错误发生的确切时间。
  • 检查明显问题的跟踪 从错误开始,向后工作,直到找到失败的测试的开始。记下上次失败测试开始设置的确切时间。检查这个范围内的所有sql。是sql 正好你期待什么?行数是否正确?交易 ID 是否正确? (对于不在事务中的每个语句,transactionId 列应该不同,对于事务中的每个语句都应该相同)。如果您不匹配 BEGIN TRAN/COMMIT TRAN/ROLLBACK TRAN,则 transactionId 会通知您。
  • 将数据库恢复到失败的测试设置之前 将其恢复到新数据库,以便我们可以比较原始数据库和副本。首先使用“RESTORE DATABASE .... WITH NORECOVERY”恢复完整备份。然后使用“RESTORE LOG .. WTIH STOPAT, RECOVERY”恢复事务日志备份,并在失败的测试设置之前指定一个时间。
  • 验证数据库状态 检查可能尚未清理的测试数据。一切都是应该的吗?如果没有,您可以再次将数据库恢复到更早的点。您正在寻找在测试开始之前数据库处于良好、已知状态的时间点。
  • 将 DB 还原到发生错误之前的正确位置 如果您有空间,请还原到另一个新数据库。检查导致PK违规的数据。如果再次运行有问题的语句,是否会出现错误?验证它是否发生。
  • 如果没有发生,您的问题很可能是不匹配的事务处理。如果您之前错过了 COMMIT,则您可能有一个尚未打开的事务。当您使用 STOPAT 恢复时,任何未提交的事务都将被回滚。这也可以解释单独运行测试如何工作,但它们一起失败。
  • 如果确实发生了,则向后工作,直到找到问题为止。在弄清楚之前,您可能需要多次恢复数据库。您的过程将是恢复数据库、检查跟踪、检查数据、恢复到不同点、检查跟踪、检查数据等。
  • 如果在这一切之后您仍然不知所措,那么您可能希望使用数据库快照作为单元测试的一部分进行调查。基本上,创建数据库快照,设置和运行测试,拆卸替换为将数据库恢复到快照。这将保证每次测试前后都有相同的数据库。

  • 2012 Management Studio 具有改进的数据库还原向导,使时间点还原变得非常容易。 祝你好运!

    关于sql-server - MSTest 单元测试 (VS 2012) 与 SQL Server,间歇性主键冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15953905/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com