MassTransit 服务总线配置和单元测试
MassTransit Service Bus Configuration and Unit Tests
对于 MassTransit,在设置新服务总线时必须声明 endpoint/type;但是,我正在尝试删除该依赖项,以便在对消费者进行测试时,我可以利用环回端点,但一旦投入生产,它将使用实际的 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();
}
}
使用构造函数注入:
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。
为了使用 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
的其他东西
对于 MassTransit,在设置新服务总线时必须声明 endpoint/type;但是,我正在尝试删除该依赖项,以便在对消费者进行测试时,我可以利用环回端点,但一旦投入生产,它将使用实际的 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();
}
}
使用构造函数注入:
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。
为了使用 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
的其他东西