【问题标题】:Unit Test fails on Run All but not on Run Selected Tests with all selected单元测试在 Run All 但在 Run Selected Tests with all selected 时失败
【发布时间】:2012-12-30 05:55:19
【问题描述】:

我遇到了一些奇怪的行为。如果我在测试资源管理器中单击“全部运行”,那么我的 1 个单元测试将失败,但如果我选择所有测试并单击“运行选定的测试”,则单元测试通过。

失败的测试在我正在测试的 dll 代码中定义的类型上引发反射错误:System.Reflection.TargetException: Non-static method requires a target.。这个类似乎没有什么奇怪的——在 dll 中定义了许多其他类,反射很满意。我在下面包含了测试堆栈跟踪。

NB 这是一个复杂的测试 - 它从 .xlsx 文件中读取输入和预期答案,使用 xlsx 中的数据填充 LocalDb,使用 LocalDB 中的数据执行计算,然后将计算结果与预期值进行比较。但是,正如我所说的那样,当我运行所有测试(使用全选>运行选定测试)时它正在工作并且工作。

Run All 有什么不同?任何见解将不胜感激。

我尝试过干净和重建,但没有运气。捕获和记录反射错误表明 GetValue 调用正在为我尝试访问该类型的每个属性抛出 - 但仅在由“全部运行”运行且仅在这一类型上运行时? (如果我发现错误,那么所有其他类型的所有 GetValues 都会成功)。

堆栈跟踪

Test Name:  IT_CheckCashOnly1DepositOutputValues
Test FullName:  Lib.AE.Tests.Integration.CalculationTests.IT_CheckCashOnly1DepositOutputValues
Test Source:    c:\netreturn.co.za\Main\NetReturn\Lib.AE.Tests\IntegrationTests\CalculationTest.cs : line 23
Test Outcome:   Failed
Test Duration:  0:00:00.1661906

Result Message: 
Test method Lib.AE.Tests.Integration.CalculationTests.IT_CheckCashOnly1DepositOutputValues threw exception: 
System.Reflection.TargetException: Non-static method requires a target.
Result StackTrace:  
at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at Lib.AE.Xlsx.XlsxHelper.Compare[T](T expected, T calculated, ExcelWorksheet ws, Int32 r, Int32 colStart, Boolean& valid) in c:\netreturn.co.za\Main\NetReturn\Lib.AE\Xlsx\XlsxHelper.cs:line 101
at Lib.AE.Xlsx.XlsxWorkSheet_SharePNL.CompareXlsx(ExcelPackage pck, List`1 expectedXlsx, ValuationCalculation calc) in c:\netreturn.co.za\Main\NetReturn\Lib.AE\Xlsx\XlsxSharePNL.cs:line 143
at Lib.AE.Tests.Integration.CalculationTests.CheckCalculationResults(String xlsxDocToLoad, WorkSheets testingScenarios) in c:\netreturn.co.za\Main\NetReturn\Lib.AE.Tests\IntegrationTests\CalculationTest.cs:line 64
at Lib.AE.Tests.Integration.CalculationTests.IT_CheckCashOnly1DepositOutputValues() in c:\netreturn.co.za\Main\NetReturn\Lib.AE.Tests\IntegrationTests\CalculationTest.cs:line 23

解决方案

结果证明这是 (a) 我的问题 - 我的单元测试与另一个单元测试共享状态以及 (b) 订单问题。请注意,TestExplorer 将以哪个顺序运行您的测试并不明显。我创建了一个新的 UnitTestProject,其中包含 2 个 UnitTest .cs 文件和三个 TestMethod,即:

UnitTest1.cs

    [TestMethod]
    public void ONE_AAA() {}

    [TestMethod]
    public void ONE_BBB() {}

    [TestMethod]
    public void ONE_CCC() {}

UnitTest2.cs

    [TestMethod]
    public void TWO_CCC() {}

    [TestMethod]
    public void TWO_BBB() {}

    [TestMethod]
    public void TWO_AAA() {}

然后通过两种方法运行这些测试,即 (1) Run All (2) Select all 和 Run Selected Tests,并记录 TestExplorer 启动测试的顺序。运行选定测试的结果相当不直观:

-- Run All
2013-01-16 11:53:47.4062 INFO TestInitialize: ONE_AAA
2013-01-16 11:53:47.4122 INFO TestCleanup: ONE_AAA
2013-01-16 11:53:47.4122 INFO TestInitialize: ONE_BBB
2013-01-16 11:53:47.4122 INFO TestCleanup: ONE_BBB
2013-01-16 11:53:47.4122 INFO TestInitialize: ONE_CCC
2013-01-16 11:53:47.4282 INFO TestCleanup: ONE_CCC
2013-01-16 11:53:47.4282 INFO TestInitialize: TWO_CCC
2013-01-16 11:53:47.4282 INFO TestCleanup: TWO_CCC
2013-01-16 11:53:47.4282 INFO TestInitialize: TWO_BBB
2013-01-16 11:53:47.4282 INFO TestCleanup: TWO_BBB
2013-01-16 11:53:47.4282 INFO TestInitialize: TWO_AAA
2013-01-16 11:53:47.4282 INFO TestCleanup: TWO_AAA

-- Select All > Run Selected
2013-01-16 11:55:26.0139 INFO TestInitialize: TWO_BBB
2013-01-16 11:55:26.0139 INFO TestCleanup: TWO_BBB
2013-01-16 11:55:26.0249 INFO TestInitialize: ONE_BBB
2013-01-16 11:55:26.0249 INFO TestCleanup: ONE_BBB
2013-01-16 11:55:26.0249 INFO TestInitialize: TWO_AAA
2013-01-16 11:55:26.0249 INFO TestCleanup: TWO_AAA
2013-01-16 11:55:26.0249 INFO TestInitialize: TWO_CCC
2013-01-16 11:55:26.0249 INFO TestCleanup: TWO_CCC
2013-01-16 11:55:26.0249 INFO TestInitialize: ONE_CCC
2013-01-16 11:55:26.0249 INFO TestCleanup: ONE_CCC
2013-01-16 11:55:26.0249 INFO TestInitialize: ONE_AAA
2013-01-16 11:55:26.0249 INFO TestCleanup: ONE_AAA

【问题讨论】:

  • 请发布您的测试代码。
  • 它太大而无法发布 - 这是我的整个代码库(问题仅在我运行所有代码时才会出现)。甚至失败的单个单元测试也很大。我现在正在尝试解决这个问题 - 即看看我是否可以分离出一个仍然表现出相同行为的较小的单元测试项目,但可能需要一段时间。
  • +1 用于发布详细解决方案
  • 我也有这个问题。我意识到我在一个类中有一个静态变量,不是每次 [Test] 都被重置
  • 你是如何记录测试运行的顺序的?

标签: .net unit-testing exception-handling visual-studio-2012


【解决方案1】:

您的[TestInitialize] 方法在每次测试之前运行。从中删除任何依赖于单个测试的代码并将其放入单独的测试中。

【讨论】:

  • 我不认为这是与多个测试有关的问题(即另一个单元测试更改状态会影响失败测试的运行) - 因为它在我运行多个测试时有效。它与“全部运行”和反射有关。知道“Run All”有什么不同吗?嗯..实际上记录单元测试运行的顺序对我来说更快,以验证“全选>运行选定”是否以与“全部运行”相同的顺序运行测试。在尝试在较小的单元测试中引起相同的行为之前,我会先尝试一下(根据我上面的评论)。
【解决方案2】:

我过去曾因运行多个单元测试而陷入困境,因为测试运行的顺序可能不是它们在测试类中声明的顺序,实际上可能是测试的顺序方法名称。例如如果我有

[Test]
public void PreviousTest()
{
}

[Test]
public void LaterTest()
{
}

然后LaterTest 将首先运行,因为它的名称按字母顺序出现在PreviousTest 之前。

如果您的所有测试都是完全独立的,这无关紧要,但是如果它们正在修改共享资源,那么如果您期望 LaterTest 的更改不会对 @987654325 产生任何影响,那么您可能会出现异常行为@ 因为它被宣布为第二个。

【讨论】:

  • 谢谢Dean,这毕竟是订单问题。选择测试和“运行选定的”可以使用不同的顺序来“运行所有”。反射异常是一个红鲱鱼(由订单问题以及失败测试与先前测试之间的依赖关系引起。我将在我的问题中写一些额外的注释以帮助其他人解决此类问题
【解决方案3】:

确保您的成员在设置范围内被初始化,否则它们可以被重用。

[TestFixture]
public class RegistrationInteractorTests
{
    private  IRegistrationService _registrationService;
    private  IRegistrationValidationService _registrationValidationService;
  ......

    [SetUp]
    public void Init()
    {
        _registrationService = A.Fake<IRegistrationService>();
        _registrationValidationService = A.Fake<IRegistrationValidationService>();
    }

....

}

// 错误的方式是这样的:

 [TestFixture]
    public class RegistrationInteractorTests
    {
        protected readonly IRegistrationService _registrationService = A.Fake<IRegistrationService>();

        protected readonly IRegistrationValidationService _registrationValidationService =
            A.Fake<IRegistrationValidationService>();



        [SetUp]
        public void Init()
        {

        }

【讨论】:

    【解决方案4】:

    我们已经尝试调查这个问题一周了。确保所有测试项目都使用相同版本的 DLL,尤其是 Nuget 包。

    问题是,当您执行“全部运行”时,所有 TEST 项目中使用的所有库都放在一个文件夹中(类似于 MyApp\TestResults\Deploy_user1 2018-11-20 15_52_15\Out)。并且因为这些 Dll 库发生了冲突。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-09-28
      • 2014-08-23
      • 1970-01-01
      • 2022-12-10
      • 2017-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多