如何配置 TestClusterBuilder 以便测试集群可以访问 SMSProvider?

How to configure TestClusterBuilder such that the test cluster has access to SMSProvider?

我正在尝试按照他们的教程进行测试: Link to Orleans test docs

但是显示的配置非常简单:

var builder = new TestClusterBuilder();
var cluster = builder.Build();
cluster.Deploy();

并且没有显示如何添加 SMSProvider。

假设我有以下测试:

    [Fact]
    public async Task SaysHelloCorrectly()
    {
        var hello = _cluster.GrainFactory.GetGrain<ISomeGrain>(Guid.NewGuid(), "<Some stream ID>", "Some.Class.Path");
        var guid = Guid.NewGuid();
        var streamProvider = _cluster.Client.GetStreamProvider("SMSProvider");
        var photoStream = streamProvider.GetStream<string>(guid, "<Some stream ID>");
        await photoStream.OnNextAsync("Hi");
        Assert.Equal("Hello, World", "Hello, World");
    }

然后我得到一个错误:

var streamProvider = _cluster.Client.GetStreamProvider("SMSProvider");

如:

[xUnit.net 00:00:02.02]     Tests.SaysHelloCorrectly [FAIL]
Failed Tests.FilterTests.SaysHelloCorrectly [8 ms]
Error Message:
  System.Collections.Generic.KeyNotFoundException : SMSProvider

我认为正确配置 ClusterFixture 是解决方案的一部分,或者我在单元测试中获取 StreamProvider 的方式不正确。

所有代码如下所示:

集群集合:

using System;
using Orleans.TestingHost;
using Xunit;

namespace Tests {

    [CollectionDefinition(ClusterCollection.Name)]
    public class ClusterCollection : ICollectionFixture<ClusterFixture>
    {
        public const string Name = "ClusterCollection";
    }
}

集群夹具:

public class ClusterFixture : IDisposable
{
    private sealed class Configurator : ISiloBuilderConfigurator
    {
        public void Configure(ISiloHostBuilder siloBuilder)
        {
            siloBuilder.AddSimpleMessageStreamProvider("SMSProvider");
            siloBuilder.AddMemoryGrainStorage("PubSubStore");
        }
    }
    public ClusterFixture()
    {
        var builder = new TestClusterBuilder();
        builder.AddSiloBuilderConfigurator<Configurator>();
        this.Cluster = builder.Build();
        this.Cluster.Deploy();
    }

    public void Dispose()
    {
        this.Cluster.StopAllSilos();
    }

    public TestCluster Cluster { get; private set; }
}

一些测试:

 [Collection(ClusterCollection.Name)]
    public class SomeTests
    {
        private readonly TestCluster _cluster;

        public SomeTests(ClusterFixture fixture)
        {
            _cluster = fixture.Cluster;
        }

        [Fact]
        public async Task SaysHelloCorrectly()
        {
            var hello = _cluster.GrainFactory.GetGrain<ISomeGrain>(Guid.NewGuid(), "<Some stream ID>", "Some.Class.Path");
            var guid = Guid.NewGuid();
            var streamProvider = _cluster.Client.GetStreamProvider("SMSProvider");
            var photoStream = streamProvider.GetStream<string>(guid, "<Some stream ID>");
            await photoStream.OnNextAsync("Hi");
            Assert.Equal("Hello, World", "Hello, World");
        }
    }

设置需要改进。您可以从 Orleans GitHub 官方页面查看此样本:https://github.com/dotnet/orleans/blob/main/test/TesterInternal/StreamingTests/SMSStreamingTests.cs

因此,在您的 ClusterFixture class 中,您应该添加 SiloConfigurator:

private class SiloConfigurator : ISiloConfigurator
{
  public void Configure(ISiloBuilder hostBuilder) =>
     hostBuilder.AddSimpleMessageStreamProvider("SMSProvider")
                .AddMemoryGrainStorage("PubSubStore");
}

ClientConfiguretor:

private class ClientConfiguretor : IClientBuilderConfigurator
{
  public void Configure(IConfiguration configuration, IClientBuilder clientBuilder) => 
    clientBuilder.AddSimpleMessageStreamProvider("SMSProvider");
}

然后在您的 ClusterFixture 构造函数中:

public ClusterFixture()
{
    var builder = new TestClusterBuilder();
    builder.AddSiloBuilderConfigurator<SiloConfigurator>();
    builder.AddClientBuilderConfigurator<ClientConfiguretor>();
    this.Cluster = builder.Build();
    this.Cluster.Deploy();
}