Orleans을 사용한 단위 테스트
이 자습서에서는 조직이 올바르게 작동하는지 확인하기 위해 단위 테스트를 하는 방법을 보여 줍니다. 조직을 단위 테스트하는 두 가지 주요 방법이 있으며 선택하는 방법은 테스트하는 기능 형식에 따라 달라집니다. Microsoft.Orleans.TestingHost NuGet 패키지를 사용하여 조직에 대한 테스트 사일로를 만들거나 Moq와 같은 모의 프레임워크를 사용하여 조직이 상호 작용하는 Orleans 런타임의 일부를 모의할 수 있습니다.
TestCluster
사용
Microsoft.Orleans.TestingHost
NuGet 패키지에는 기본적으로 두 개의 사일로로 구성된 메모리 내 클러스터를 만드는 데 사용할 수 있는 TestCluster가 포함되어 있으며, 이는 조직을 테스트하는 데 사용할 수 있습니다.
using Orleans.TestingHost;
namespace Tests;
public class HelloGrainTests
{
[Fact]
public async Task SaysHelloCorrectly()
{
var builder = new TestClusterBuilder();
var cluster = builder.Build();
cluster.Deploy();
var hello = cluster.GrainFactory.GetGrain<IHelloGrain>(Guid.NewGuid());
var greeting = await hello.SayHello("World");
cluster.StopAllSilos();
Assert.Equal("Hello, World!", greeting);
}
}
메모리 내 클러스터를 시작하는 오버헤드로 인해 TestCluster
를 만들고 여러 테스트 사례에서 다시 사용해야 할 수도 있습니다. 예를 들어 xUnit의 클래스 또는 컬렉션 픽스쳐를 사용하여 이 작업을 수행할 수 있습니다.
여러 테스트 사례 간에 TestCluster
를 공유하려면 먼저 픽스쳐 형식을 만듭니다.
using Orleans.TestingHost;
public sealed class ClusterFixture : IDisposable
{
public TestCluster Cluster { get; } = new TestClusterBuilder().Build();
public ClusterFixture() => Cluster.Deploy();
void IDisposable.Dispose() => Cluster.StopAllSilos();
}
다음으로, 컬렉션 픽스쳐를 만듭니다.
[CollectionDefinition(Name)]
public sealed class ClusterCollection : ICollectionFixture<ClusterFixture>
{
public const string Name = nameof(ClusterCollection);
}
이제 테스트 사례에서 TestCluster
를 다시 사용할 수 있습니다.
using Orleans.TestingHost;
namespace Tests;
[Collection(ClusterCollection.Name)]
public class HelloGrainTestsWithFixture(ClusterFixture fixture)
{
private readonly TestCluster _cluster = fixture.Cluster;
[Fact]
public async Task SaysHelloCorrectly()
{
var hello = _cluster.GrainFactory.GetGrain<IHelloGrain>(Guid.NewGuid());
var greeting = await hello.SayHello("World");
Assert.Equal("Hello, World!", greeting);
}
}
xUnit은 모든 테스트가 완료되고 메모리 내 클러스터 사일로가 중지될 때 ClusterFixture
형식의 Dispose() 메서드를 호출합니다. TestCluster
에는 클러스터에서 사일로를 구성하는 데 사용할 수 있는 TestClusterOptions를 허용하는 생성자도 있습니다.
사일로에서 종속성 주입을 사용하여 조직에서 서비스를 사용할 수 있도록 하는 경우 다음 패턴도 사용할 수 있습니다.
using Microsoft.Extensions.DependencyInjection;
using Orleans.TestingHost;
namespace Tests;
public sealed class ClusterFixtureWithConfig : IDisposable
{
public TestCluster Cluster { get; } = new TestClusterBuilder()
.AddSiloBuilderConfigurator<TestSiloConfigurations>()
.Build();
public ClusterFixtureWithConfig() => Cluster.Deploy();
void IDisposable.Dispose() => Cluster.StopAllSilos();
}
file sealed class TestSiloConfigurations : ISiloConfigurator
{
public void Configure(ISiloBuilder siloBuilder)
{
siloBuilder.ConfigureServices(static services =>
{
// TODO: Call required service registrations here.
// services.AddSingleton<T, Impl>(/* ... */);
});
}
}
모의 사용
Orleans는 또한 시스템의 많은 부분을 모의할 수 있도록 하며, 많은 시나리오에서 이를 통해 조직을 가장 손쉽게 단위 테스트할 수 있습니다. 이 접근 방식에는 제한 사항(예: 재진입 및 직렬화 예약)이 있으며, 단위 테스트에만 사용되는 코드가 조직에 포함되어야 할 수 있습니다. Orleans TestKit는 이러한 제한 사항 중 많은 부분을 단계별로 수행하는 대체 방법을 제공합니다.
예를 들어 테스트 중인 조직이 다른 조직과 상호 작용한다고 가정해 보겠습니다. 그러한 다른 조직을 모의할 수 있도록 하려면 테스트 중인 조직의 GrainFactory 멤버를 모의해야 합니다. 기본적으로 GrainFactory
는 일반 protected
속성이지만 대부분의 모의 프레임워크에서 모의할 수 있으려면 속성이 public
및 virtual
이어야 합니다. 따라서 가장 먼저 GrainFactory
를 public
및 virtual
속성으로 만들어야 합니다.
public new virtual IGrainFactory GrainFactory
{
get => base.GrainFactory;
}
이제 Orleans 런타임 외부에서 조직을 만들고 모의 작업을 사용하여 GrainFactory
의 동작을 제어할 수 있습니다.
using Xunit;
using Moq;
namespace Tests;
public class WorkerGrainTests
{
[Fact]
public async Task RecordsMessageInJournal()
{
var data = "Hello, World";
var journal = new Mock<IJournalGrain>();
var worker = new Mock<WorkerGrain>();
worker
.Setup(x => x.GrainFactory.GetGrain<IJournalGrain>(It.IsAny<Guid>()))
.Returns(journal.Object);
await worker.DoWork(data)
journal.Verify(x => x.Record(data), Times.Once());
}
}
여기서는 Moq을 사용하여 테스트 중인 조직 WorkerGrain
을 만듭니다. 즉, 모의된 IJournalGrain
을 반환할 수 있도록 GrainFactory
의 동작을 재정의할 수 있습니다. 그런 다음, WorkerGrain
이 예상대로 IJournalGrain
와 상호 작용하는지 확인할 수 있습니다.
.NET