C# EventHub PartitionContext类设计

C# EventHub PartitionContext类设计,c#,azure,unit-testing,azure-eventhub,C#,Azure,Unit Testing,Azure Eventhub,我正在尝试测试IEventProcessor的实现。然而,我有一个困难的时期,因为它是不可能真正模拟PartitionContext类() 例如,我无法验证是否正确调用了CheckpointAsync()方法,因为ICheckpointer接口是内部的,而实际的方法不是虚拟的。 此外,我不能注入我自己的ICheckpointManager实例,因为允许注入的构造函数是内部的 让所有东西都内部化的设计决策是什么,这会让我嘲笑这个类 要么这是一个非常糟糕的设计,要么我遗漏了一些东西。是的,测试这一点

我正在尝试测试IEventProcessor的实现。然而,我有一个困难的时期,因为它是不可能真正模拟PartitionContext类()

例如,我无法验证是否正确调用了CheckpointAsync()方法,因为ICheckpointer接口是内部的,而实际的方法不是虚拟的。 此外,我不能注入我自己的ICheckpointManager实例,因为允许注入的构造函数是内部的

让所有东西都内部化的设计决策是什么,这会让我嘲笑这个类


要么这是一个非常糟糕的设计,要么我遗漏了一些东西。

是的,测试这一点需要很多工作。下面是要做的

因此,您创建了一个包装器:

public interface ICheckPointer
{
    Task CheckpointAsync(PartitionContext context);
}

public class CheckPointer : ICheckPointer
{
    public Task CheckPointAsync(PartitionContext context)
    {
        return context.CheckpointAsync();
    }
}
在单元测试方法中,现在可以模拟接口并检查是否调用了
CheckPointAsync

现在,您的
IEventProcessor
实现应该接受
ICheckPointer
的实例:

public class SampleEventProcessor : IEventProcessor
{
    private ICheckPointer checkPointer;

    public SampleEventProcessor(ICheckPointer checkPointer)
    {
        this.checkPointer = checkPointer;
    }

    public Task OpenAsync(PartitionContext context)
    {
        return Task.FromResult<object>(null);
    }

    public async Task ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> events)
    {
        ...

        await checkPointer.CheckpointAsync(context);
    }

    public async Task CloseAsync(PartitionContext context, CloseReason reason)
    {
        return Task.FromResult<object>(null);
    }
}
您可以这样创建EventProcessor:

await host.RegisterEventProcessorFactoryAsync(new SampleEventProcessor(new CheckPointer()));
在单元测试中,您现在可以执行以下操作(基于NSubstitute):

var mock=Substitute.For();
var样本=新的SampleEventProcessor(模拟);
wait sample.ProcessEventsAsync(new PartitionContext(),null);
mock.Received().CheckPointAsync(Arg.Any());

警告:未编译代码,因此可能存在一些语法错误。至少它应该给你一个如何进行的基本概念。

Azure.Messaging.EventHubs库中一个相当新的添加是
EventHubsModelFactory
,它为单元测试提供了一些有用的静态方法

ParitionContext partitionCtx = EventHubsModelFactory.PartitionContext(partitionId);

“new PartitionContext()”导致编译错误,因为构造函数显然不是公共的。如果在发布问题时是公共的,请参阅。您使用的是什么NuGet软件包?抱歉,我正在使用Microsoft.Azure.EventHubs.Processor命名空间中的PartitionContext。我正在使用NuGet软件包v2.0.1。查看这个版本,似乎没有提供公共空构造函数的版本。我试图使用可用的构造函数,但无法模拟或实例化所需的EventProcessorHost参数。您好W.Poust,谢谢您的帖子。你能更新你的答案,更清楚地解释这是如何回答原来的问题的吗?
var mock = Substitute.For<ICheckPointer>();
var sample = new SampleEventProcessor(mock);
await sample.ProcessEventsAsync(new PartitionContext(), null);
mock.Received().CheckPointAsync(Arg.Any<PartitionContext>());
ParitionContext partitionCtx = EventHubsModelFactory.PartitionContext(partitionId);