2017-10-24 3 views
0

다양한 콘텐츠로 소비자 메시지를 보낼 수있는 MassTransit 소비자 주변에서 테스트를하고 싶습니다. 소비자가 "작업하고"메시지를 릴레이하는 메시지의 내용을 기반으로합니다.InMemoryTestFixture를 사용하여 대중 교통 소비자 테스트

내가 가지고있는 문제는 두 가지 테스트를 실행할 때, 별도의 테스트 픽스처에서 두 번째 테스트를 방해하는 것으로 보입니다. 그러나 개별적으로 실행하면 각 테스트가 성공적으로 실행됩니다.

MassTransit 테스트 프로젝트를 살펴본 후에 내가 가지고있는 문제를 보여주기 위해 몇 가지 예제 테스트 코드를 생각해 냈습니다.

[TestFixture] 
public class PingPongMessageTestFixture : InMemoryTestFixture 
{ 
    private PongConsumer _pongConsumer; 
    protected override void ConfigureInMemoryReceiveEndpoint(IInMemoryReceiveEndpointConfigurator configurator) 
    { 
     _received = Handled<IPongMessage>(configurator); 
    } 

    protected override void PreCreateBus(IInMemoryBusFactoryConfigurator configurator) 
    { 
     var _pingConsumer = new PingConsumer(); 
     _pongConsumer = new PongConsumer(); 
     configurator.ReceiveEndpoint("test_ping_queue", e => 
     { 
      e.Consumer(() => _pingConsumer); 
     }); 

     configurator.ReceiveEndpoint("test_pong_queue", e => 
     { 
      e.Consumer(() => _pongConsumer); 
     }); 
    } 

    Task<ConsumeContext<IPongMessage>> _received; 

    [Test] 
    public async Task test_how_to_test_consumers() 
    { 
     await Bus.Publish<IPingMessage>(new { MessageId = 100 }); 
     await _received; 

     Assert.IsTrue(_pongConsumer.hitme); 
     Assert.AreEqual(100, _pongConsumer.pongMessage.MessageId); 
    } 

    public class PingConsumer : IConsumer<IPingMessage> 
    { 
     public Task Consume(ConsumeContext<IPingMessage> context) 
     { 
      context.Publish<IPongMessage>(new { context.Message.MessageId }); 
      return Task.CompletedTask; 
     } 
    } 

    public class PongConsumer : IConsumer<IPongMessage> 
    { 
     internal bool hitme; 
     internal IPongMessage pongMessage; 
     public Task Consume(ConsumeContext<IPongMessage> context) 
     { 
      hitme = true; 
      pongMessage = context.Message; 
      return Task.CompletedTask; 
     } 
    } 

    public interface IPingMessage 
    { 
     int MessageId { get; set; } 
    } 

    public interface IPongMessage 
    { 
     int MessageId { get; set; } 
    } 
} 

이 테스트는 핑 소비자에게 메시지를 보내고 핑 소비자에게 메시지를 보냅니다.

이 자체로 작동하고 핑 소비자가 pong 메시지를 보낼지 테스트합니다. 실생활 시나리오에서 "핑 (ping)"소비자는 업데이트 메시지를 다른 서비스에 보내고 퐁 소비자는 테스트에 사용 된 테스트 소비자 일뿐입니다.

이 질문에 대한 두 번째 테스트 픽스처가있는 경우 두 테스트를 함께 실행하면 실패합니다. 개별적으로 통과 할지라도.

시험은 같은 일

[TestFixture] 
public class DingDongMessageTestFixture : InMemoryTestFixture 
{ 
    private DongConsumer _pongConsumer; 
    protected override void ConfigureInMemoryReceiveEndpoint(IInMemoryReceiveEndpointConfigurator configurator) 
    { 
     _received = Handled<IDongMessage>(configurator); 
    } 

    protected override void PreCreateBus(IInMemoryBusFactoryConfigurator configurator) 
    { 
     var _dingConsumer = new DingConsumer(); 
     _dongConsumer = new DongConsumer(); 
     configurator.ReceiveEndpoint("test_ding_queue", e => 
     { 
      e.Consumer(() => _dingConsumer); 
     }); 

     configurator.ReceiveEndpoint("test_dong_queue", e => 
     { 
      e.Consumer(() => _dongConsumer); 
     }); 
    } 

    Task<ConsumeContext<IDongMessage>> _received; 

    [Test] 
    public async Task test_how_to_test_consumers() 
    { 
     await Bus.Publish<IDingMessage>(new { MessageId = 100 }); 
     await _received; 

     Assert.IsTrue(_pongConsumer.hitme); 
     Assert.AreEqual(100, _pongConsumer.pongMessage.MessageId); 
    } 

    public class DingConsumer : IConsumer<IDingMessage> 
    { 
     public Task Consume(ConsumeContext<IDingMessage> context) 
     { 
      context.Publish<IDongMessage>(new { context.Message.MessageId }); 
      return Task.CompletedTask; 
     } 
    } 

    public class DongConsumer : IConsumer<IDongMessage> 
    { 
     internal bool hitme; 
     internal IDongMessage pongMessage; 
     public Task Consume(ConsumeContext<IDongMessage> context) 
     { 
      hitme = true; 
      pongMessage = context.Message; 
      return Task.CompletedTask; 
     } 
    } 

    public interface IDingMessage 
    { 
     int MessageId { get; set; } 
    } 

    public interface IDongMessage 
    { 
     int MessageId { get; set; } 
    } 
} 

이것은 Masstransit 소비자를 테스트하기위한 좋은 방법입니다합니까?

그렇다면 테스트 필러마다 InMemoryTestFixture를 재설정해야합니까?

답변

2

테스트 픽스쳐에서 나는 어떤 충돌이있을 것이라고는 생각하지 않지만, NUnit과의 상호 작용으로 인해 사용되는 기본 클래스 상속으로 인해 내가 모르는 뭔가가있을 수 있습니다.

InMemoryTestHarness을 직접 사용하면 (텍스트 고정 장치와 동일한 기능이지만 테스트 프레임 워크 종속성이 없음) 두 개의 동시 실행 테스트간에 상호 작용이 일어나지 않아야합니다.

당신의 접근 방식은해야 할 일이지만, 다시 조명기 대신 InMemoryTestHarness을 사용하는 것이 좋습니다.

예 시험 링크 : https://github.com/MassTransit/MassTransit/blob/master/src/MassTransit.Tests/Testing/ConsumerTest_Specs.cs

+0

어떻게 당신은 매개 변수가없는 생성자가없는 테스트 장치로 소비자를 연결 것인가? – theHaggis

+0

이것은 나를 위해 작동합니다. _consumer = _harness.Consumer (() => {return (PingConsumer) pingConsumer;}); – theHaggis

관련 문제