Files
Entkube/tests/EntKube.Provisioning.Tests/Domain/ServiceInstanceTests.cs
2026-05-13 14:01:32 +02:00

127 lines
3.9 KiB
C#

using EntKube.Provisioning.Domain;
using FluentAssertions;
namespace EntKube.Provisioning.Tests.Domain;
public class ServiceInstanceTests
{
[Fact]
public void Provision_WithValidInputs_CreatesInstanceInPendingState()
{
// Arrange & Act — Request provisioning of a MinIO instance.
Guid environmentId = Guid.NewGuid();
Guid clusterId = Guid.NewGuid();
ServiceInstance instance = ServiceInstance.Provision(
environmentId,
ServiceType.MinIO,
"tenant-storage",
"minio-system",
clusterId);
// Assert — Starts pending until the reconciler deploys it.
instance.Id.Should().NotBe(Guid.Empty);
instance.EnvironmentId.Should().Be(environmentId);
instance.ClusterId.Should().Be(clusterId);
instance.ServiceType.Should().Be(ServiceType.MinIO);
instance.Name.Should().Be("tenant-storage");
instance.Namespace.Should().Be("minio-system");
instance.DesiredState.Should().Be(ServiceState.Running);
instance.CurrentState.Should().Be(ServiceState.Pending);
}
[Fact]
public void Provision_WithEmptyName_ThrowsArgumentException()
{
// Arrange & Act
Action act = () => ServiceInstance.Provision(Guid.NewGuid(), ServiceType.MinIO, "", "ns", Guid.NewGuid());
// Assert
act.Should().Throw<ArgumentException>()
.WithParameterName("name");
}
[Fact]
public void MarkRunning_UpdatesCurrentState()
{
// Arrange
ServiceInstance instance = ServiceInstance.Provision(Guid.NewGuid(), ServiceType.CloudNativePG, "db", "cnpg-system", Guid.NewGuid());
// Act
instance.MarkRunning();
// Assert
instance.CurrentState.Should().Be(ServiceState.Running);
instance.LastReconcileAt.Should().NotBeNull();
}
[Fact]
public void RequestDecommission_SetsDesiredStateToDecommissioned()
{
// Arrange
ServiceInstance instance = ServiceInstance.Provision(Guid.NewGuid(), ServiceType.Keycloak, "auth", "keycloak-system", Guid.NewGuid());
instance.MarkRunning();
// Act — Tenant admin decides to tear down this service.
instance.RequestDecommission();
// Assert — Desired state changes but current state remains until reconciler acts.
instance.DesiredState.Should().Be(ServiceState.Decommissioned);
instance.CurrentState.Should().Be(ServiceState.Running);
}
[Fact]
public void ServiceType_IncludesGitea()
{
// Gitea is a shared service that can be provisioned on a cluster,
// so ServiceType must include it as a valid option.
ServiceType type = ServiceType.Gitea;
type.Should().BeDefined();
}
[Fact]
public void ServiceType_IncludesHarbor()
{
// Harbor is a shared container registry that can be provisioned
// on a cluster, so ServiceType must include it.
ServiceType type = ServiceType.Harbor;
type.Should().BeDefined();
}
[Fact]
public void Provision_Gitea_CreatesInstanceInPendingState()
{
// Gitea should be provisionable just like any other service type.
ServiceInstance instance = ServiceInstance.Provision(
Guid.NewGuid(), ServiceType.Gitea, "team-gitea", "gitea", Guid.NewGuid());
instance.ServiceType.Should().Be(ServiceType.Gitea);
instance.CurrentState.Should().Be(ServiceState.Pending);
}
[Fact]
public void Provision_Harbor_CreatesInstanceInPendingState()
{
// Harbor should be provisionable just like any other service type.
ServiceInstance instance = ServiceInstance.Provision(
Guid.NewGuid(), ServiceType.Harbor, "team-harbor", "harbor", Guid.NewGuid());
instance.ServiceType.Should().Be(ServiceType.Harbor);
instance.CurrentState.Should().Be(ServiceState.Pending);
}
}