Skip to content

Commit f8a4c39

Browse files
iammukeshmclaude
andcommitted
fix(tests): fix Hangfire job timing race in integration tests
The production Hangfire server uses a 30s SchedulePollingInterval, meaning enqueued tenant provisioning jobs could wait up to 30s before pickup — longer than the test's 30s polling timeout. Fix: - Override AddHangfireServer in test factory with 1s polling interval - Increase WaitForProvisioningAsync timeout from 30s to 60s - Fail fast on provisioning failure instead of silently continuing - Throw TimeoutException instead of silently returning on timeout Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6054e02 commit f8a4c39

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

src/Tests/Integration.Tests/Infrastructure/FshWebApplicationFactory.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ protected override void ConfigureWebHost(IWebHostBuilder builder)
8888
builder.ConfigureServices(services =>
8989
{
9090
services.AddHangfire(config => config.UseInMemoryStorage());
91+
services.AddHangfireServer(options =>
92+
{
93+
options.SchedulePollingInterval = TimeSpan.FromSeconds(1);
94+
options.HeartbeatInterval = TimeSpan.FromSeconds(5);
95+
options.Queues = ["default", "email"];
96+
options.WorkerCount = 2;
97+
});
9198
services.TryAddTransient<IJobService, HangfireService>();
9299

93100
services.PostConfigure<JwtBearerOptions>(

src/Tests/Integration.Tests/Tests/Multitenancy/TenantIsolationTests.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ private static async Task CreateTenantAsync(HttpClient rootClient, string tenant
102102
response.StatusCode.ShouldBe(HttpStatusCode.Created);
103103
}
104104

105-
private static async Task WaitForProvisioningAsync(HttpClient client, string tenantId, int maxRetries = 30)
105+
private static async Task WaitForProvisioningAsync(HttpClient client, string tenantId, int maxRetries = 60)
106106
{
107107
for (int i = 0; i < maxRetries; i++)
108108
{
@@ -112,14 +112,22 @@ private static async Task WaitForProvisioningAsync(HttpClient client, string ten
112112
if (statusResponse.IsSuccessStatusCode)
113113
{
114114
var content = await statusResponse.Content.ReadAsStringAsync();
115-
if (content.Contains("Success", StringComparison.OrdinalIgnoreCase)
116-
|| content.Contains("Completed", StringComparison.OrdinalIgnoreCase))
115+
if (content.Contains("Completed", StringComparison.OrdinalIgnoreCase))
117116
{
118117
return;
119118
}
119+
120+
if (content.Contains("Failed", StringComparison.OrdinalIgnoreCase))
121+
{
122+
throw new InvalidOperationException(
123+
$"Tenant {tenantId} provisioning failed: {content}");
124+
}
120125
}
121126

122127
await Task.Delay(1000);
123128
}
129+
130+
throw new TimeoutException(
131+
$"Tenant {tenantId} provisioning did not complete within {maxRetries} seconds.");
124132
}
125133
}

0 commit comments

Comments
 (0)