1

현재 RX 서술문 내에서 TPL 함수 테스트 문제로 고심하고 있습니다. 문제는 내가 관찰 대상에 접근 할 수 없다는 것입니다.RX + TPL + 테스팅

  • TPL을 혼합하지 말고 RX
  • TPL에 대한 래퍼 만들기 : 내가 좋아하는 많은 기사와 조언을 주위에 인터넷 검색과 발견했습니다

    [Test] 
    public void TestRaceConditions() 
    { 
        // Arrange 
        TestScheduler testScheduler = new TestScheduler(); 
        List<string> source = new List<string> {"Hello"}; 
        List<string> results = new List<string>(); 
    
        source.ToObservable().SelectMany(v => Task.Run(() => 
        { 
         Thread.Sleep(10000); // Simulate long running operation 
         return v; 
        }).ToObservable(testScheduler)) 
        .ObserveOn(testScheduler) 
        .Subscribe(s => results.Add(s)); 
    
        // Act 
        testScheduler.Start(); 
    
        Assert.That(results.Count, Is.EqualTo(1)); 
        Assert.That(results[0], Is.EqualTo("Hello")); 
    } 
    

    : 여기

    내 테스트입니다 완성 된 작업을 조롱하고 반환 할 수있는 코드. ==> 그러나 통합 테스트는 어떻습니까? 나는 또한 시도 무엇

사용자 정의 TaskScheduler를 만드는 것입니다,하지만 나는 모든 Task.RunTask.Factory.StartNew로 교체해야합니다.

그래서 질문은 :

  • 어떻게 작업하거나 모든 요소가 처리 완료되면 내가 아는 Schedulers 테스트에서 관찰 제어를 얻으려면?

UPDATE : 실제 예

public class ResultController : IDisposable 
{ 
    private readonly IServiceClient _serviceClient; 
    private readonly IDisposable _subscription; 

    public ResultController(IEventProvider eventProvider, 
          IServiceClient serviceClient, 
          ISchedulerProvider schedulerProvider) 
    { 
     _serviceClient = serviceClient; 
     _subscription = eventProvider.Events.SelectMany(e => LoadDataAsync(e.Id)) 
              .SubscribeOn(schedulerProvider.TaskPool) 
              .ObserveOn(schedulerProvider.Dispatcher) 
              .Subscribe(OnNewDataLoaded); 
    } 

    private void OnNewDataLoaded(Data data) 
    { 

    } 

    public async Task<Data> LoadDataAsync(int id) 
    { 
     ////return Task.Run(() => 
     ////{ 
     //// Thread.Sleep(10000); 
     //// return new Data(); 
     ////}); 

     return await _serviceClient.LoadDataByIdAsync(id); 
    } 

    public void Dispose() 
    { 
     _subscription.Dispose(); 
    } 
} 

이 솔루션은 문제없이 생산에 작동하지만 테스트에서 내가 통제하에 작업이 없습니다.

  • ServiceClient을 조롱하고 완료된 Task을 반환하는 것이 좋습니다.
  • 그러나 SpecFlow가있는 IntegrationTests에서 동기화 작업을 해킹하지 않고 작업이 완료된 시점을 알 수 없습니다.
+3

답변은 Rx와 TPL을 섞어서는 안됩니다. 그냥 Rx를 사용하십시오. 왜 TPL이 필요한가요? – Enigmativity

+0

@Enigmativity 고마워요 .--) 그래,하지만 이미 서버에서 데이터를로드하는 데 작업을 사용하는 많은 코드가있는 경우 알 수 있습니다. 그것을 제거 할 수는 없습니다. 프로덕션 코드에서도 마찬가지입니다. – crip

+0

인공적인 예제가 아닌 실제 코드를 보여줄 수 있습니까? – Enigmativity

답변

0

내가 어떻게 여기에 무슨 것은 그들이이 완료되기 전에 작업의 결과를 주장한다는 것입니다 생각 :

// starts a work in a different thread 
// and continues the test right after firing work up 
testScheduler.Start(); 

// results here are empty for a 10 seconds 
Assert.That(results.Count, Is.EqualTo(1)); 
Assert.That(results[0], Is.EqualTo("Hello")); 

당신은 당신이 예약하고 작업의 연속에 가입 여기에 수행 할 수있는 작업 Task.Run으로 작업 배열을 소개하고 해당 작업을 추가하고 기다릴 때까지 기다릴 수 있습니다.

사용자 정의 스케줄러를 사용하면 시뮬레이션 작업으로 인해 도움이되지 않을 수도 있습니다. 스레드가 깨어날 때까지 10 초 동안 기다려야합니다. 다른 방법으로는 Task.Delay 메쏘드를 사용하는 것이고, 이것은 당신의 테스트 스케줄러에 의해 무시 될 수 있습니다.

+0

그래,하지만 난 못생긴 sychronization 속성을 폭로해야 해. 나는 또한 Task.Delay도 Thread.Sleep도 싶지 않아. 데모 용이었습니다. 이미 실제 시나리오를 추가했습니다. – crip

+0

그러면 테스트 중에 기다리는 시간을 더할 수 있습니다 – VMAtm

+0

어느 쪽이 벗겨지지 않는 테스트를 도입 할 것인가? 이것이 내가 이것을 묻는 근본 원인입니다. :-) – crip