【问题标题】:Should you unsubscribe from events and dispose of objects in nunit tests?您是否应该取消订阅事件并在 nunit 测试中处理对象?
【发布时间】:2019-05-20 18:24:26
【问题描述】:

是否有关于我们是否应该在使用 NUnit 的单元测试中进行引用清理的指南?

[Test]
public void Test_AsyncAction_EventRaised()
{
  var someClassToTest = new someClassToTest();
  var mre = new ManualResetEvent(false);
  someClassToTest.SomeEvent += () => {
    mre.Set();
  }

  someClassToTest.SomeAsyncAction();    
  var eventFired = mre.WaitOne(TimeSpan.FromSeconds(1));

  Assert.IsTrue(eventFired);

  //unsub event?
  //dispose MRE?
}

在正常的运行时情况下,不取消订阅意味着只要 SomeClassToTest 仍在内存中,测试夹具就会泄漏。如果 SomeClassToTest 有内存泄漏,那么这意味着夹具也会泄漏。

实现 IDisposable 的类(例如 ManualResetEvent)意味着如果我们不调用 Dispose,它们就会泄漏资源。这也适用于单元测试场景吗?

【问题讨论】:

  • @Çöđěxěŕ 那个人似乎在问“我如何总是清理?”而这个更像是“我总是需要清理吗?”
  • @Çöđěxěŕ 这个问题是关于如何确保他们的数据库在测试后得到清理。在这种情况下,我知道如何清理......我只是不确定这是否是 NUnit 框架的最佳实践。
  • @BillTarbell / @Broots Waymb 好的,我删除了重复的标志。比尔,一般来说,实现IDisposable 的经验法则任何东西 应该始终释放资源。就指导方针而言,我目前不确定。除了这样做有什么伤害之外,最好是做点什么而不是不做参考,对吧?
  • someClassToTest 实例不会停留在测试本身之外的范围内。由于整个对象超出范围,因此它不会在其事件的处理程序中持有对对象的根引用。一个对象很少能比它的事件的处理程序长很多,而且处理程序中的那些对象保留起来很昂贵。因此,需要取消订阅事件应该是相当罕见的。如果你经常这样做,你可能做错了什么。
  • 对象将保留在内存中,只要所有测试都执行甚至更少,取决于测试执行者。因此,除非实例没有引用某些外部资源,否则最好不要显式清理它。

标签: c# unit-testing nunit


【解决方案1】:

我的偏好始终是让测试代码进行适当的清理(除非可能在测试失败的情况下 - 在这种情况下,我接受来自该测试的资源泄漏)。这是由于以下原因:

  • 我也将测试代码视为文档。因此,我希望它能够很好地使用我的 SUT(被测系统)以及其他库。
  • 测试的一个用例是在内存分析器下运行它们以查找 SUT 中的资源泄漏。但是,如果测试本身会导致资源泄漏,那么从此类分析器中获得有用的结果会更加困难 - 您可能只见树木不见森林。
  • 如果您希望以后能够将测试合并到更大的测试套件中,那么资源泄漏就会总结起来。根据资源的类型(打开的文件、线程等),这可能会导致问题。

【讨论】:

  • 在 NUnit 下实现这一点的一个简单方法是让您的测试类一次性使用。当夹具完成时,NUnit 将处理它。当然,这仅适用于在 TestFixture 的生命周期内持有的资源,而不是在单个测试期间获得的资源。这些应该在 TearDown 中处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-17
  • 2021-09-30
  • 1970-01-01
  • 2014-10-29
  • 2020-10-26
  • 2012-06-15
相关资源
最近更新 更多