Skip to content

Skipped Tests - Technical Debt

This document tracks tests that have been skipped due to underlying architectural issues that require deeper fixes. Each entry explains the root cause and what would be needed to properly fix the tests.

Summary

Category Count Priority
MassTransit Saga Test Harness Issues 4 Medium
Project AutoApproveJoinRequests Setup 7 Low
StudyReferenceFileParser Interface Extraction 1 Medium
Production Code Behavior Changes 1 Low
Angular PDF.js Module Loading Issues 3 Low

MassTransit Saga Tests (4 tests)

Location: src/services/project-management/SyRF.ProjectManagement.Endpoint.Tests/SearchImportJob_Test.cs

Tests Affected

  1. execute_parsing_activity_and_reach_completed_state_when_events_arrive_in_order
  2. reach_error_state_publish_error_event_and_fault_future_messages_when_initialise_activity_throws_exception
  3. execute_parsing_activity_and_reach_completed_state_when_events_arrive_out_of_order
  4. run_initialise_activity_on_file_upload_started_event

Root Cause

The MassTransit InMemoryTestHarness has timing and state isolation issues when running multiple saga tests together. Tests pass individually but fail when run as a group due to:

  1. Shared state in test harness - Even with [Collection("Saga Tests")] and DisableParallelization = true, the test harness appears to leak state between tests
  2. Activity DI resolution - Activities registered via .Activity(x => x.OfType<T>()) in the state machine are not being properly resolved from the test's DI container
  3. Timing issues - Async message consumption and state transitions have race conditions in the test harness

Fix Required

  • Option A (Recommended): Migrate to MassTransit's newer TestHarness pattern with proper test isolation per the MassTransit testing documentation
  • Option B: Create integration tests that run against a real RabbitMQ instance with proper message broker isolation
  • Option C: Refactor to use the IStateMachineActivityFactory pattern for better activity resolution in tests

References


Project AutoApproveJoinRequests Tests (7 tests)

Location: src/libs/project-management/SyRF.ProjectManagement.Core.Tests/ProjectShould.cs and ProjectMembershipTests.cs

Tests Affected

  1. Register_Should_Add_Membership_To_Collection (2 variants)
  2. Deregister_Should_Remove_Membership_From_Collection (2 variants)
  3. GetMembershipFor_Should_Return_Membership (2 variants)
  4. GetGroups_Should_Return_Membership (2 variants)
  5. GetRoles_Should_Throws_Exception (2 variants)
  6. Registration_Request_With_Self_Authorisation_Should_Not_Be_Pending_Membership
  7. Registration_Request_With_Self_Authorisation_Should_Be_Authorised_Member

Root Cause

The Project constructor does not accept or set the AutoApproveJoinRequests property:

// Current constructor signature (Project.cs:25-28)
public Project(string name, Guid creatorId, string protocolUrl,
    bool isPublic, string inclusionCriteria,
    string exclusionCriteria, int schemaVersion, ICollection<string> keywords, ...)

The isPublic parameter is the 4th argument, but the tests assume this controls auto-approval. In reality, AutoApproveJoinRequests defaults to false and can only be set via UpdateProjectSettings().

When AutoApproveJoinRequests is false, calling RequestToJoin() creates a pending join request instead of immediately adding the user to memberships.

Fix Required

Option A (Recommended): Add autoApproveJoinRequests parameter to the Project constructor:

public Project(string name, Guid creatorId, string protocolUrl,
    bool isPublic, bool autoApproveJoinRequests, string inclusionCriteria, ...)
{
    // ...
    AutoApproveJoinRequests = autoApproveJoinRequests;
}

Option B: Update tests to explicitly call UpdateProjectSettings() after construction to set AutoApproveJoinRequests = true.

Option C: Create a test helper method that creates properly configured projects for testing.


StudyReferenceFileParser Interface Extraction (1 test)

Location: src/libs/project-management/SyRF.ProjectManagement.Core.Tests/ProjectManagementServiceTests.cs

Test Affected

  • CreateSearchAsync_Should_Throw_An_InvalidOperationException

Root Cause

StudyReferenceFileParser is a concrete class with non-virtual methods. Moq cannot override non-virtual methods, causing this error:

System.NotSupportedException: Non-overridable members
(here: StudyReferenceFileParser.ParseStudiesAsync) may not be used in
setup / verification expressions.

The class has a complex constructor requiring 6 dependencies:

public StudyReferenceFileParser(
    IEnumerable<IStudyParseImplementation> studyParseImplementations,
    S3Settings s3Settings,
    AppSettingsConfig appSettingsConfig,
    ILoggerFactory loggerFactory,
    IFileService fileService,
    IPmUnitOfWork unitOfWork)

Fix Required

Extract an IStudyReferenceFileParser interface from the concrete class:

public interface IStudyReferenceFileParser
{
    Task<FileParseResult> ParseStudiesAsync(
        ReferenceFileParseJob job,
        Func<Study, CancellationToken, Task> onStudyParsed,
        IEnumerable<SimpleStudyUpdate>? studyUpdates = null,
        CancellationToken cancellationToken = default,
        Guid? existingSearchId = null);

    // Other public methods...
}

Then update ProjectManagementService to depend on the interface instead of the concrete class.


Production Code Behavior Change (1 test)

Location: src/libs/project-management/SyRF.ProjectManagement.Core.Tests/ProjectMembershipTests.cs

Test Affected

  • Should_Throw_When_Authorising_Investigator_Without_Pending_Join_Request

Root Cause

The test expects ApprovePendingJoinRequest() to throw an InvalidOperationException when called for an investigator without a pending join request. However, the production code behavior has changed and no longer throws an exception in this scenario.

Fix Required

  1. Investigate why ApprovePendingJoinRequest() no longer throws
  2. Either:
  3. Option A: Restore the expected exception behavior if it was accidentally removed
  4. Option B: Update the test to match the new expected behavior
  5. Option C: Remove the test if the validation is no longer needed

Angular PDF.js Module Loading Issues (3 tests)

Location: src/services/web/src/app/pdf-tools/

Tests Affected

  1. PdfLoaderService > should be created
  2. PdfPageComponent > should create
  3. PdfDisplayComponent > should create

Root Cause

The PDF tools tests trigger dynamic import('pdfjs-dist') which causes unhandled errors in CI:

  1. Esbuild bundling - Angular's @angular/build:unit-test uses esbuild, which bundles pdfjs-dist at compile time before Vitest's mocks in vitest-setup.ts can intercept it
  2. Module initialization - When the bundled pdfjs-dist module initializes, it throws InvalidPDFException during internal validation
  3. Async timing - The import completes ~15 seconds after the test starts, causing Vitest to attribute the error to whatever test happens to be running at that moment

The mock in vitest-setup.ts doesn't work because esbuild processes modules before the setup file runs:

// vitest-setup.ts - ineffective due to bundling order
vi.mock('pdfjs-dist', () => pdfMock);

Error seen in CI:

InvalidPDFException: Invalid PDF structure.
❯ BaseExceptionClosure node_modules/pdfjs-dist/build/pdf.js:540:29

Fix Required

Option A (Current workaround): Exclude src/app/pdf-tools/**/*.spec.ts from CI runs in angular.json.

Option B (Recommended): Configure esbuild to externalize pdfjs-dist during testing so the mock can intercept it. This requires Angular build configuration changes.

Option C: Create a PDF_LOADER injection token that can be mocked at the Angular DI level:

// In pdf-loader.service.ts
export const PDF_LOADER = new InjectionToken<() => Promise<typeof pdfjsLib>>('PDF_LOADER', {
  providedIn: 'root',
  factory: () => async () => await import('pdfjs-dist')
});

// In tests
providers: [
  { provide: PDF_LOADER, useValue: () => Promise.resolve(mockPdfjsLib) }
]

Priority Recommendations

High Priority (Fix Soon)

None - all critical tests pass

Medium Priority (Fix in Next Sprint)

  1. MassTransit Saga Tests - These test critical business logic around search import workflows
  2. StudyReferenceFileParser Interface - Enables proper unit testing of file parsing logic

Low Priority (Fix When Convenient)

  1. Project AutoApproveJoinRequests - Tests are for edge cases, core membership logic is tested elsewhere
  2. ApprovePendingJoinRequest behavior - Investigate if this is intentional production code change
  3. Angular PDF.js Tests - Tests are minimal stubs, PDF functionality is tested via integration tests

  • None currently. Consider creating an ADR if significant refactoring is undertaken.

Changelog

  • 2025-12-03: Added Angular PDF.js module loading issues documentation
  • 2025-12-03: Initial documentation of skipped tests