You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何Mock Azure Event Hubs的EventHubProducerClient类及指定方法?

如何Mock EventHubProducerClient进行单元测试(无需修改原类)

方案一:直接用Moq Mock EventHubProducerClient的虚方法

Azure SDK的EventHubProducerClient类(Azure.Messaging.EventHubs包)中,CreateBatchAsync和SendAsync均为虚方法,因此可直接用Moq框架Mock这个具体类,无需修改原代码或添加额外包装层。

步骤:

  1. 安装必要的NuGet包:

    Install-Package Moq
    Install-Package xunit
    Install-Package xunit.runner.visualstudio
    Install-Package Azure.Messaging.EventHubs
    
  2. 测试代码示例:
    假设你有一个依赖EventHubProducerClient的业务类EventSenderService:

public class EventSenderService
{
    private readonly EventHubProducerClient _producer;

    public EventSenderService(EventHubProducerClient producer)
    {
        _producer = producer;
    }

    public async Task SendEvents(IEnumerable<string> messages)
    {
        var eventDataList = messages.Select(m => new EventData(Encoding.UTF8.GetBytes(m)));
        using var batch = await _producer.CreateBatchAsync();
        
        foreach (var evt in eventDataList)
        {
            if (!batch.TryAdd(evt))
            {
                throw new InvalidOperationException("事件过大无法加入批次");
            }
        }

        await _producer.SendAsync(batch);
    }
}

对应的单元测试:

using Moq;
using Azure.Messaging.EventHubs;
using Azure.Messaging.EventHubs.Producer;
using Xunit;
using System.Text;

public class EventSenderServiceTests
{
    [Fact]
    public async Task SendEvents_ShouldCallSendAsyncWithValidBatch()
    {
        // 初始化Mock对象
        var mockProducer = new Mock<EventHubProducerClient>();
        var mockBatch = new Mock<EventDataBatch>();

        // 设置CreateBatchAsync返回Mock批次
        mockProducer
            .Setup(p => p.CreateBatchAsync(It.IsAny<CancellationToken>()))
            .ReturnsAsync(mockBatch.Object);

        // 设置批次的TryAdd行为为总是成功
        mockBatch
            .Setup(b => b.TryAdd(It.IsAny<EventData>()))
            .Returns(true);

        // 注入Mock实例,初始化被测试服务
        var service = new EventSenderService(mockProducer.Object);
        var testMessages = new List<string> { "test-event-1", "test-event-2" };

        // 执行测试方法
        await service.SendEvents(testMessages);

        // 验证行为符合预期
        mockProducer.Verify(p => p.CreateBatchAsync(CancellationToken.None), Times.Once);
        mockProducer.Verify(p => p.SendAsync(mockBatch.Object, It.IsAny<CancellationToken>()), Times.Once);
        mockBatch.Verify(b => b.TryAdd(It.Is<EventData>(e => Encoding.UTF8.GetString(e.Body.Span) == "test-event-1")), Times.Once);
        mockBatch.Verify(b => b.TryAdd(It.Is<EventData>(e => Encoding.UTF8.GetString(e.Body.Span) == "test-event-2")), Times.Once);
    }
}

方案二:接口包装方案(针对无法直接Mock的场景)

如果你的EventHubProducerClient版本过旧(比如使用废弃的Microsoft.Azure.EventHubs包),方法并非虚方法,可采用接口包装方案,但需调整原类的依赖方式(注入接口而非具体类)。仅当允许修改原类依赖逻辑时使用:

  1. 定义接口:
public interface IEventHubProducer
{
    Task<EventDataBatch> CreateBatchAsync(CancellationToken cancellationToken = default);
    Task SendAsync(EventDataBatch batch, CancellationToken cancellationToken = default);
}
  1. 实现包装类:
public class EventHubProducerWrapper : IEventHubProducer
{
    private readonly EventHubProducerClient _innerClient;

    public EventHubProducerWrapper(EventHubProducerClient innerClient)
    {
        _innerClient = innerClient;
    }

    public Task<EventDataBatch> CreateBatchAsync(CancellationToken cancellationToken = default)
    {
        return _innerClient.CreateBatchAsync(cancellationToken);
    }

    public Task SendAsync(EventDataBatch batch, CancellationToken cancellationToken = default)
    {
        return _innerClient.SendAsync(batch, cancellationToken);
    }
}
  1. 修改原类依赖IEventHubProducer,之后即可Mock该接口进行测试,逻辑与方案一一致,仅需将Mock对象替换为IEventHubProducer。

内容的提问来源于stack exchange,提问作者Ethan Backhus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 13:52:45