2017-11-11 63 views
0

所有消息應發佈到消息總線:如何單元測試Rx.Net的foreach訂閱

upstream.Get().ForEachAsync(async e => await _bus.Publish(e, cancellationToken)); 

我想單元測試來驗證publish方法被調用正確:

[Theory, AutoMoqData] 
    public void Publish_ShouldPublishAllDataSources(
     [Frozen]Mock<IBus> bus, 
     [Frozen]Mock<IUpstream> upstream, 
     SUT sut, 
     TestScheduler scheduler, 
     CancellationToken cancellationToken 
     ) 
    { 
     { 
      Arrange(); 
      Act(); 
      Assert(); 
     } 
     ITestableObservable<Event> inputObservable; 

     void Arrange() 
     { 
      inputObservable = 
        scheduler.CreateColdObservable(
         OnNext(1L,new Event("e1")), 
         OnNext(1L,new Event("e2")), 
         OnNext(1L,new Event("e3")) 
        ); 
      upstream 
      .Setup(c => c.Get()) 
      .Returns(inputObservable); 


     } 

     void Act() 
     { 
      sut.Exercise(cancellationToken); 
      //Do sth with scheduller to fire all events 
      //I've tested these: 
      //scheduler.Start(); 
      //scheduler.AdvanceTo(30000L); 
     } 


     void Assert() 
     { 
      inputObservable.ForEach(e => 
       bus.Verify(b => 
        b.Publish(e, cancellationToken) 
       )); 
     } 
    } 

但無論我嘗試測試永不停止。

更新:

下面是完整的生產代碼:

class SUT 
{ 
    IUpstream _upstream; 
    public SUT(IUpstream upstream) 
    { 
      _upstream = upstream; 
    } 
    void Exercise(CancellationToken cancellationToken) 
    { 
     _upstream .Get() 
       .ForEachAsync(async 
        e => await _bus.Publish(e, cancellationToken)); 
    } 
} 


interface IUpstream 
{ 
    IObservable<string> Get(); 
} 

interface IBus 
{ 
    void Publish<T>(T,System.Threading.CancellationToken) 
} 
+4

你真的需要爲此提供[MCVE。我們可以運行一些代碼來查看行爲。最好只是一個簡單的控制檯應用。 – Enigmativity

+0

感謝您的更新,但是您是否嘗試製作[mcve],以便在控制檯應用中運行? – Enigmativity

+0

我不知道你的意思是「在控制檯應用程序中運行代碼的測試工具需要更多儀式」。這對我沒有意義。 – Enigmativity

回答

1

ITestableObservable<T>.Messages應當用於斷言不是ITestableObservable<T>本身。

void Assert() 
    { 
     inputObservable 
       .Messages.ToList() 
       .ForEach(e => 
       bus.Verify(b => 
        b.Publish(e.Value.Value, cancellationToken))); 
    } 

所以動作要像下面這樣:

void Act() 
    { 
     sut.Exercise(cancellationToken); 
     scheduler.Start(); 
     //OR: 
     //scheduler.AdvanceBy(1L); 
    }