DockerHealthcheckTests.cs 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. using DotNet.Testcontainers.Builders;
  2. using DotNet.Testcontainers.Containers;
  3. using Xunit.Abstractions;
  4. namespace Tests.E2e;
  5. public class DockerHealthcheckTests(ITestOutputHelper output) {
  6. private const string _dockerImage = "rackpeek:ci";
  7. private static readonly TimeSpan _healthDeadline = TimeSpan.FromSeconds(60);
  8. [Fact]
  9. public async Task Container_Reports_Healthy_Status_Via_Docker_HEALTHCHECK() {
  10. await using IContainer container = new ContainerBuilder(_dockerImage)
  11. .WithPortBinding(8080, true)
  12. .WithWaitStrategy(
  13. Wait.ForUnixContainer()
  14. .UntilContainerIsHealthy())
  15. .Build();
  16. using var cts = new CancellationTokenSource(_healthDeadline);
  17. try {
  18. // StartAsync blocks until the wait strategy succeeds. If the image
  19. // has no HEALTHCHECK instruction Docker reports `health: none` forever,
  20. // so we bound the wait — the cancellation token forces a fast failure
  21. // rather than letting the test hang.
  22. await container.StartAsync(cts.Token);
  23. Assert.Equal(TestcontainersStates.Running, container.State);
  24. Assert.Equal(TestcontainersHealthStatus.Healthy, container.Health);
  25. }
  26. catch (Exception) {
  27. output.WriteLine($"Container did not reach 'Healthy' within {_healthDeadline.TotalSeconds:F0}s.");
  28. output.WriteLine($"Container state: {container.State}");
  29. output.WriteLine($"Container health: {container.Health}");
  30. try {
  31. (string Stdout, string Stderr) logs = await container.GetLogsAsync();
  32. output.WriteLine("==== CONTAINER STDOUT ====");
  33. output.WriteLine(logs.Stdout);
  34. output.WriteLine("==== CONTAINER STDERR ====");
  35. output.WriteLine(logs.Stderr);
  36. }
  37. catch (Exception logEx) {
  38. output.WriteLine($"Failed to capture container logs: {logEx.Message}");
  39. }
  40. throw;
  41. }
  42. }
  43. }