2017-10-24 10 views
0

さまざまなコンテンツを持つコンシューマメッセージを送信できるMassTransitコンシューマの周りにテストを設計したいと考えています。消費者がメッセージを中継してメッセージを中継するメッセージの内容に基づいています。InMemoryTestFixtureを使用してMassTransitコンシューマをテストする

私が持っている問題は、別々のテストフィクスチャで2つのテストを実行しているときに、2つ目のテストを妨害しているようです。しかし、個々のテストを個別に実行すると、正常に実行されます

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; } 
    } 
} 

このテストでは、ping消費者にメッセージを送信し、ping消費者にメッセージを送信します。

これは単独で動作し、pingコンシューマがpongメッセージを送信することをテストします。現実のシナリオでは、「ping」コンシューマは、更新メッセージを別のサービスに送信し、ポンコンシューマは、テストで使用される単なるテストコンシューマです。

私はこの質問に対して非常に似ている2番目のテストフィクスチャを持っている場合、両方のテストを一緒に実行すると失敗します。個々には合格しますが。

テストは同じこと

[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を直接使用すると(テキストフィクスチャと同じ機能ですが、テストフレームワークの依存関係はありません)、同時に実行する2つのテストの間に相互作用が起こらないようにしてください。

あなたのアプローチはそれを行うべきですが、もう一度、私はフィクスチャの代わりに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

関連する問題