Testowanie jednostkowe za pomocą polecenia Orleans
W tym samouczku pokazano, jak przetestować ziarna, aby upewnić się, że działają prawidłowo. Istnieją dwa główne sposoby testowania ziarna, a wybrana metoda będzie zależeć od typu testowych funkcji. Microsoft .Orleans. Pakiet NuGet TestingHost może służyć do tworzenia silosów testowych dla ziarna lub można użyć platformy pozorowania, takiej jak Moq , aby wyśmiewać części Orleans środowiska uruchomieniowego, z którymi współdziała ziarno.
Użyj interfejsu TestCluster
Pakiet Microsoft.Orleans.TestingHost
NuGet zawiera TestCluster , który może służyć do tworzenia klastra w pamięci składającego się domyślnie z dwóch silosów, których można użyć do testowania ziarna.
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);
}
}
Ze względu na obciążenie związane z uruchamianiem klastra w pamięci możesz utworzyć TestCluster
klaster i użyć go ponownie w wielu przypadkach testowych. Na przykład można to zrobić przy użyciu klas lub kolekcji xUnit.
Aby udostępnić element TestCluster
między wieloma przypadkami testowym, najpierw utwórz typ urządzenia:
using Orleans.TestingHost;
public sealed class ClusterFixture : IDisposable
{
public TestCluster Cluster { get; } = new TestClusterBuilder().Build();
public ClusterFixture() => Cluster.Deploy();
void IDisposable.Dispose() => Cluster.StopAllSilos();
}
Następnie utwórz oprawę kolekcji:
[CollectionDefinition(Name)]
public sealed class ClusterCollection : ICollectionFixture<ClusterFixture>
{
public const string Name = nameof(ClusterCollection);
}
Teraz możesz ponownie użyć elementu TestCluster
w swoich przypadkach testowych:
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);
}
}
Funkcja xUnit wywołuje metodę Dispose() typu po zakończeniu ClusterFixture
wszystkich testów, a silosy klastra w pamięci zostaną zatrzymane. TestCluster
Ma również konstruktor, który akceptuje TestClusterOptions , że może służyć do konfigurowania silosów w klastrze.
Jeśli używasz iniekcji zależności w silosie do udostępniania usług ziarnom, możesz również użyć tego wzorca:
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>(/* ... */);
});
}
}
Korzystanie z makiety
Orleans umożliwia również pozorowanie wielu części systemu, a w wielu scenariuszach jest to najprostszy sposób jednostkowego testowania ziarna. Takie podejście ma ograniczenia (na przykład wokół planowania ponownej analizy i serializacji) i może wymagać, aby ziarna zawierały kod używany tylko przez testy jednostkowe. Zestaw Orleans TestKit zapewnia alternatywne podejście, które kroków po stronie wielu z tych ograniczeń.
Załóżmy na przykład, że testowane ziarno współdziała z innymi ziarnami. Aby móc wyśmiewać te inne ziarna, musisz również wyśmiewać GrainFactory członka ziarna pod testem. Domyślnie GrainFactory
jest to normalna protected
właściwość, ale większość szyderczych struktur wymaga, aby właściwości były public
i virtual
mogły je wyśmiewać. Więc pierwszą rzeczą, którą musisz zrobić, jest utworzenie GrainFactory
właściwości public
i virtual
:
public new virtual IGrainFactory GrainFactory
{
get => base.GrainFactory;
}
Teraz możesz utworzyć ziarno poza Orleans środowiskiem uruchomieniowym i użyć pozorowania, aby kontrolować zachowanie elementu 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());
}
}
W tym miejscu utworzysz ziarno pod testem , WorkerGrain
przy użyciu moq, co oznacza, że można zastąpić zachowanie GrainFactory
tak, aby zwracał wyśmiewany IJournalGrain
. Następnie możesz sprawdzić, czy interakcja WorkerGrain
z elementem jest oczekiwana IJournalGrain
.