Skip to content

NullReferenceException in CucumberMessageFactory.ToTestStepStarted during scenario cleanup causes scenario to be silently omitted from HTML report #1083

Description

@thogr

Environment

Reqnroll.NUnit: 3.3.4 (also reproduced on 3.3.3)
NUnit: 4.5.1
NUnit3TestAdapter: 4.5.0
NUnitRetry.ReqnrollPlugin: 2.0.17
.NET: 9.0

Description

When a scenario step fails with an exception, Reqnroll's CucumberMessagePublisher crashes with its own NullReferenceException during scenario cleanup (OnAfterLastStepAsync). As a result, the scenario is silently omitted from the HTML report even though the failure is correctly printed to the console/standard output.

Steps to reproduce

Intermittent — triggered when a step throws an exception during execution. Occurs under parallel test runs. No minimal repro has been isolated yet.

Stack trace (3.3.4)

System.NullReferenceException : Object reference not set to an instance of an object.
   at Reqnroll.Formatters.PayloadProcessing.Cucumber.CucumberMessageFactory.ToTestStepStarted(TestStepExecutionTracker testStepExecutionTracker)
   at Reqnroll.Formatters.ExecutionTracking.TestStepExecutionTracker.ProcessEvent(StepStartedEvent stepStartedEvent)
   at Reqnroll.Formatters.ExecutionTracking.TestCaseExecutionTracker.ProcessEvent(StepStartedEvent stepStartedEvent)
   at Reqnroll.Formatters.ExecutionTracking.PickleExecutionTracker.ProcessEvent(StepStartedEvent stepStartedEvent)
   at Reqnroll.Formatters.ExecutionTracking.FeatureExecutionTracker.ProcessEvent(StepStartedEvent stepStartedEvent)
   at Reqnroll.Formatters.PubSub.CucumberMessagePublisher.StepStartedEventHandler(StepStartedEvent stepStartedEvent)
   at Reqnroll.Formatters.PubSub.CucumberMessagePublisher.OnEventAsync(IExecutionEvent executionEvent)
   at Reqnroll.Events.TestThreadExecutionEventPublisher.PublishEventAsync(IExecutionEvent executionEvent)
   at Reqnroll.Infrastructure.TestExecutionEngine.<ExecuteStepAsync>...MoveNext()
   at Reqnroll.Infrastructure.TestExecutionEngine.OnAfterLastStepAsync()
   at Reqnroll.TestRunner.CollectScenarioErrorsAsync()
   at <FeatureClass>.ScenarioCleanupAsync()

On 3.3.3 the top frame was TestStepExecutionTracker.ProcessEvent instead of CucumberMessageFactory.ToTestStepStarted, suggesting a refactor moved the null dereference one level deeper without fixing the root cause.

Expected behavior

When a step fails, the scenario should still appear in the HTML report as failed.

Actual behavior

The scenario is absent from the HTML report. The failure is only visible in console/standard output.

Additional context

The crash occurs during OnAfterLastStepAsync → CollectScenarioErrorsAsync, meaning Reqnroll is trying to publish a StepStartedEvent (likely for an AfterScenario hook) while the TestStepExecutionTracker is in a state that CucumberMessageFactory.ToTestStepStarted cannot handle — presumably because the previous step failure left the tracker partially initialized.

NOTE: This analysis was created by Claude Code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions