Skip to content

ArgumentNullException in TestRunAccumulator.Aggregate when test run fails internally #3510

@jundayin

Description

@jundayin

Description

When running Stryker with Microsoft Testing Platform runner, a System.ArgumentNullException is thrown with the message Value cannot be null. (Parameter 'collection') for certain mutants, causing them to be reported as not fully tested.

Error

System.ArgumentNullException: Value cannot be null. (Parameter 'collection')
   at System.Collections.Generic.List`1.AddRange(IEnumerable`1 collection)
   at Stryker.TestRunner.MicrosoftTestPlatform.SingleMicrosoftTestPlatformRunner.TestRunAccumulator.Aggregate(TestRunResult result, List`1 discoveredTests) in /_/src/Stryker.TestRunner.MicrosoftTestPlatform/SingleMicrosoftTestPlatformRunner.cs:line 366
   at Stryker.TestRunner.MicrosoftTestPlatform.SingleMicrosoftTestPlatformRunner.RunAllTestsAsync(IReadOnlyList`1 assemblies, Int32 mutantId, IReadOnlyList`1 mutants, TestUpdateHandler update, ITimeoutValueCalculator timeoutCalc) in /_/src/Stryker.TestRunner.MicrosoftTestPlatform/SingleMicrosoftTestPlatformRunner.cs:line 441

The following is AI generated by reading source code with the stack trace and analyze the bug. Let me know if it is legit or not. If the fix could be this straightforward I will fork and create PR for the fix

Root Cause

TestRunResult has two constructors. The full constructor (line 21) correctly assigns the Messages property. The simple constructor (line 11), used for error/failure cases, never initializes Messages, leaving it null:

public TestRunResult(bool success, string message = null)
{
    TestDescriptions = new List<IFrameworkTestDescription>();
    FailingTests = !success ? TestIdentifierList.EveryTest() : TestIdentifierList.NoTest();
    ExecutedTests = TestIdentifierList.EveryTest();
    TimedOutTests = TestIdentifierList.NoTest();
    ResultMessage = message;
    Duration = TimeSpan.Zero;
    // Messages is never assigned → null
}

When RunTestsInternalAsync catches an exception, it returns new TestRunResult(false, ex.Message). This result is passed to TestRunAccumulator.Aggregate, which calls:

_messages.AddRange(result.Messages); // result.Messages is null → ArgumentNullException

Suggested Fix

Initialize Messages to an empty collection in the simple constructor in src/Stryker.TestRunner/Results/TestRunResult.cs:

public TestRunResult(bool success, string message = null)
{
    TestDescriptions = new List<IFrameworkTestDescription>();
    FailingTests = !success ? TestIdentifierList.EveryTest() : TestIdentifierList.NoTest();
    ExecutedTests = TestIdentifierList.EveryTest();
    TimedOutTests = TestIdentifierList.NoTest();
    ResultMessage = message;
    Messages = [];  // fix: initialize to empty instead of leaving null
    Duration = TimeSpan.Zero;
}

Alternatively, Aggregate could be made null-safe:

_messages.AddRange(result.Messages ?? []);

The constructor fix is preferable as it ensures consistent state for all TestRunResult instances.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions