MassTransit服务总线配置和单元测试

问题描述 投票:2回答:2

对于MassTransit,在设置新的服务总线时,必须声明端点/类型;但是,我试图删除该依赖项,以便当我对消费者进行测试时,我可以利用环回端点但是一旦在生产中,它将使用实际的msmq端点。

以下是新服务总线的示例设置:

public class ConsumerService
{
    IServiceBus _bus;

    public void Start()
    {
        // Initalize Service Bus
        _bus = ServiceBusFactory.New(x =>
        {
            //x.UseMsmq();
            x.ReceiveFrom("loopback://localhost/MyQueue");
            x.SetConcurrentConsumerLimit(1);
        });
        _bus.SubscribeConsumer(() => new MyConsumer());
    }

    public void Stop()
    {
        _bus.Dispose();
    }
}
unit-testing dependency-injection masstransit
2个回答
3
投票

使用构造函数注入:

public class ConsumerService
{
    private readonly IBusInitializer initializer;

    public ConsumerService(IBusInitializer initializer)
    {
        this.initializer = initializer;
    }

    IServiceBus _bus;

    public void Start()
    {
        // Initalize Service Bus
        _bus = ServiceBusFactory.New(x =>
        {
            this.initializer.initialize(x);
            x.SetConcurrentConsumerLimit(1);
        });
        _bus.SubscribeConsumer(() => new MyConsumer());
    }

    public void Stop()
    {
        _bus.Dispose();
    }
}

其中IInitializer是一个正确定义的接口,实现可能是:

public class LoopbackInitializer : IBusInitializer
{
    public void Initialize(WhateverXIs x)
    {
        x.ReceiveFrom("loopback://localhost/MyQueue");
    }
}

public class MsmqInitializer : IBusInitializer
{
    public void Initialize(WhateverXIs x)
    {
        x.UseMsmq();
    }
}

在测试或Composition Root中注入所需的实现。


2
投票

我使用MassTransit进行测试所做的是在接口中封装对服务总线的依赖,然后将这种依赖注入到我的类中。

bus的界面

public interface IPublishBus {
    void Publish<T>(T message) where T : class;
}

然后在生产中使用实现

public class MassTransitBridge : IPublishBus {
    private IServiceBus _ServiceBus;
    private static readonly string __SubscriptionServiceQueue;
    private static readonly string __MassTransitBridgeQueue;

    static MassTransitBridge() {
        __SubscriptionServiceQueue = ConfigurationManager.AppSettings["mtSubscriptionService"];
        __MassTransitBridgeQueue = ConfigurationManager.AppSettings["mtBridgeQueue"];
    }

    public MassTransitBridge() {
        _ServiceBus = ServiceBusFactory.New(sbc => {
            sbc.UseMsmq(mq => {
                mq.UseSubscriptionService(__SubscriptionServiceQueue);
                mq.Configurator.UseControlBus();
                mq.Configurator.SetCreateTransactionalQueues(true);
            });
            sbc.DisablePerformanceCounters();
            sbc.ReceiveFrom(__MassTransitBridgeQueue);
            sbc.UseControlBus();
            sbc.UseJsonSerializer();
        });
    }

    public void Publish<T>(T message) where T : class {
        _ServiceBus.Publish<T>(message);
    }
}

在测试时,我使用以下注入到我的服务中的Mock对象

public class PublishBusMock : IPublishBus {
    public static List<Object> Messages { get; private set; }

    public PublishBusMock() {
        Messages = new List<object>();
    }

    public void Publish<T>(T message) where T : class {
        Messages.Add(message);      
    }

    public static void ClearMessages() {
        Messages = new List<object>();
    }
}

Mock对象允许我测试object引发的正确消息是否被测试。

同样以这种方式注入它允许我换掉MassTransit用于在需要时实现IPublishBus的其他东西

© www.soinside.com 2019 - 2024. All rights reserved.