Skip to content

Refactor QuartzJobTransientRetryTests to use manual job instances consistently#106

Merged
sfmskywalker merged 2 commits intoenh/102from
copilot/sub-pr-104-again
Dec 24, 2025
Merged

Refactor QuartzJobTransientRetryTests to use manual job instances consistently#106
sfmskywalker merged 2 commits intoenh/102from
copilot/sub-pr-104-again

Conversation

Copy link
Contributor

Copilot AI commented Dec 24, 2025

The component tests were creating manual job instances with test doubles but also scheduling separate instances with Quartz, creating ambiguity about which instance was being tested.

Changes

  • Split test setup into two explicit methods:

    • CreateTestJobSetupWithoutScheduling: Tests Execute() logic directly without scheduler interaction
    • CreateTestJobSetupWithScheduling: Schedules job when verifying scheduler operations (e.g., job deletion)
  • Added documentation clarifying when scheduling is necessary vs. when direct Execute() calls suffice

Before:

private async Task CreateTestJobSetup(...) {
    var job = CreateRunWorkflowJob(failingStarter);
    await scheduler.ScheduleJob(jobDetail, trigger);  // Always scheduled, even when unused
    return (job, failingStarter, context);
}

After:

// Transient exception tests - no scheduling needed
var (job, _, context) = await CreateTestJobSetupWithoutScheduling(...);

// Non-transient test - needs scheduling to verify deletion
var (job, _, context) = await CreateTestJobSetupWithScheduling(...);

All tests remain functionally equivalent but intent is now explicit.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

…ests

The test now explicitly separates two scenarios:
- Transient exceptions: test Execute() directly without scheduling
- Non-transient exceptions: schedule job to verify deletion behavior

This clarifies that we're testing the job Execute logic directly with test doubles,
while only scheduling when needed to verify scheduler interactions.

Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com>
Copilot AI changed the title [WIP] Update Quartz.NET jobs resilience based on review feedback Refactor QuartzJobTransientRetryTests to use manual job instances consistently Dec 24, 2025
Copilot AI requested a review from sfmskywalker December 24, 2025 20:47
@sfmskywalker sfmskywalker marked this pull request as ready for review December 24, 2025 20:48
Copilot AI review requested due to automatic review settings December 24, 2025 20:48
@sfmskywalker sfmskywalker merged commit 2e30901 into enh/102 Dec 24, 2025
5 checks passed
@sfmskywalker sfmskywalker deleted the copilot/sub-pr-104-again branch December 24, 2025 20:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the test setup in QuartzJobTransientRetryTests to make the testing approach more explicit by distinguishing between tests that require Quartz scheduling and those that can test job execution logic directly.

Key Changes:

  • Split CreateTestJobSetup into two distinct methods: CreateTestJobSetupWithoutScheduling for direct execution testing and CreateTestJobSetupWithScheduling for scheduler interaction testing
  • Added comprehensive documentation explaining when each setup method should be used
  • Updated test comments to clarify the reason for using each setup approach
Comments suppressed due to low confidence (1)

test/modules/scheduling/Elsa.Scheduling.Quartz.ComponentTests/QuartzJobTransientRetryTests.cs:121

  • The two methods CreateTestJobSetupWithoutScheduling and CreateTestJobSetupWithScheduling contain significant code duplication. Consider extracting the common setup logic (lines 78-88 in the first method and 103-113 in the second) into a shared private method, then have each method call that shared method and only handle the scheduling-specific logic. This would reduce maintenance burden and make the code more DRY.
    private async Task<(RunWorkflowJob job, FailingWorkflowStarter failingStarter, IJobExecutionContext context)>
        CreateTestJobSetupWithoutScheduling(int failuresBeforeSuccess, Exception exception, string jobIdentifier)
    {
        var scheduler = await WorkflowServer.GetSchedulerAsync();
        var workflowStarter = Scope.ServiceProvider.GetRequiredService<IWorkflowStarter>();

        var failingStarter = new FailingWorkflowStarter(workflowStarter)
        {
            FailuresBeforeSuccess = failuresBeforeSuccess,
            ExceptionToThrow = exception
        };

        var job = CreateRunWorkflowJob(failingStarter);
        var (jobDetail, trigger) = CreateJobDetailAndTrigger(jobIdentifier);
        
        // Don't schedule with Quartz - we're testing the Execute method directly
        var context = CreateTestContext(scheduler, jobDetail, trigger);

        return (job, failingStarter, context);
    }

    /// <summary>
    /// Creates a test setup and schedules the job with Quartz.
    /// Use when testing behavior that involves scheduler operations (e.g., job deletion).
    /// </summary>
    private async Task<(RunWorkflowJob job, FailingWorkflowStarter failingStarter, IJobExecutionContext context)>
        CreateTestJobSetupWithScheduling(int failuresBeforeSuccess, Exception exception, string jobIdentifier)
    {
        var scheduler = await WorkflowServer.GetSchedulerAsync();
        var workflowStarter = Scope.ServiceProvider.GetRequiredService<IWorkflowStarter>();

        var failingStarter = new FailingWorkflowStarter(workflowStarter)
        {
            FailuresBeforeSuccess = failuresBeforeSuccess,
            ExceptionToThrow = exception
        };

        var job = CreateRunWorkflowJob(failingStarter);
        var (jobDetail, trigger) = CreateJobDetailAndTrigger(jobIdentifier);

        // Schedule the job with Quartz so the job can interact with the scheduler
        // (e.g., delete itself on non-transient exceptions)
        await scheduler.ScheduleJob(jobDetail, trigger);
        var context = CreateTestContext(scheduler, jobDetail, trigger);

        return (job, failingStarter, context);
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants