2012-05-24 3 views
1

.Schedule (DateTimeOffset, Action>) 항목을 사용하여 RX 스케줄러 클래스로 작업하고 있습니다. 기본적으로 나는 다시 일정을 잡을 수있는 예정된 행동을했습니다.Reactive Extensions 테스트 스케줄러 시간 경과 시뮬레이션

코드 : 내 질문 시간을 시뮬레이션 직결되는

public SomeObject(IScheduler sch, Action variableAmountofTime) 
{ 
    this.sch = sch; 
    sch.Schedule(GetNextTime(), (Action<DateTimeOffset> runAgain => 
    { 
     //Something that takes an unknown variable amount of time. 
     variableAmountofTime(); 

     runAgain(GetNextTime()); 
    }); 
} 

public DateTimeOffset GetNextTime() 
{ 
    //Return some time offset based on scheduler's 
    //current time which is irregular based on other inputs that i have left out. 
    return this.sch.now.AddMinutes(1); 
} 

variableAmountofTime 소요 시간 및 예상대로 내 코드가 동작하는지 테스트 만 예상대로 호출 트리거 수 있습니다.

대리인 내에서 테스트 스케줄러 시간을 연장하려고 시도했지만 작동하지 않습니다. 내가 쓴 그 코드의 예제는 그다지 효과가 없습니다. GetNextTime()이 1 분만 스케쥴하는 것으로 가정합니다.

[Test] 
public void TestCallsAppropriateNumberOfTimes() 
{ 
    var sch = new TestScheduler(); 

    var timesCalled = 0; 

    var variableAmountOfTime =() => 
     { 
      sch.AdvanceBy(TimeSpan.FromMinutes(3).Ticks); 
      timescalled++; 
     }; 

    var someObject = new SomeObject(sch, variableAmountOfTime); 

    sch.AdvanceTo(TimeSpan.FromMinutes(3).Ticks); 

    Assert.That(timescalled, Is.EqualTo(1)); 
} 

내가 미래에 3 분 가고 걸려 있지만 실행이 3 분 거리에 있기 때문에, 나는 3 번 트리거이 유일한 트리거 1 time..instead을보고 싶어요.

테스트 스케줄러를 사용하여 실행하는 동안 시간을 ​​어떻게 시뮬레이트 할 수 있습니까?

답변

5

좋은 질문입니다. 현재 은 Rx v1.x 및 Rx v2.0 Beta (에 있지만에서 읽음)에을 지원하지 않습니다. 중첩 된 Advance * 호출의 복잡성에 대해 설명하겠습니다.

기본적으로 Advance *는 지정된 지점까지 작업을 실행하도록 스케줄러를 시작 함을 의미합니다. 이것은 가상 스케줄러에서 시간 흐름을 나타내는 단일 논리 스레드에서 작업을 순서대로 실행하는 것과 관련됩니다. 중첩 된 고급 * 호출을 허용하면 몇 가지 질문이 제기됩니다.

중첩 된 Advance * 호출은 중첩 된 작업 루프를 실행해야합니까? 이 경우 현재 작업 항목이 중단되어 내부 루프가 실행되기 때문에 더 이상 실행 논리 스레드를 모방하지 않습니다. 사실 Advance *는 내포 된 모든 작업이 처리 될 때까지 Advance * 호출 이후 나머지 작업 (실행 예정)이 실행되지 않도록 암시 적으로 처리합니다. 이것은 미래의 작업이 실행을 끝내기 위해 과거의 작업에 의존하거나 기다릴 수없는 상황을 초래합니다. 한 가지 방법은 실제 물리적 동시성을 도입하는 것입니다.이 병렬성은 가상 시간 및 히스토리 스케줄러의 다양한 디자인 포인트를 처음부터 무효로 만듭니다.

중첩 된 Advance * 호출이 최상위 작업자 루프 디스 패칭 호출 (Advance * 또는 Start)에 어떻게 든 통신해야한다면 중첩 호출이 이후의 점으로 넘어가려고하기 때문에 예정 시간을 연장해야 할 수도 있습니다. 원래 기한. 이제 모든 종류의 것들이 이상하게 변해가고 있습니다. 시계는 Advance *에서 돌아온 후에 변경 사항을 반영하지 않으며 가장 위에있는 호출이 더 이상 예측 가능한 시간에 끝나지 않습니다.

수신 버전 2.0 RC (오는 다음 달)을 위해, 우리는이 시나리오에보고했다 및 사전 * 그것은에 따라 오버로드 의미를 필요할 것 때문에 "시간 미끄러짐"을 에뮬레이트 할 수있는 권리 일이 아니다 결정 그것이 호출 된 컨텍스트 대신, 우리는 수면 방법을 소개합니다.이 방법을 사용하면 작업 실행의 부작용없이 어떤 상황에서도 시간을 앞당길 수 있습니다. 이것을 Clock 속성을 설정하는 방법으로 생각하면서 시간을 거슬러 올라가는 것을 막을 수 있습니다. 이름은 의도를 명확하게 반영합니다.

중첩 된 Advance * 호출의 놀라운 요소를 줄이기 위해이 상황을 감지하고 InvalidOperationException 중첩 된 컨텍스트에서 throw했습니다. 반면 수면은 어디서나 호출 할 수 있습니다.

마지막주의 사항. Rx v2.0 RC에서 우리가 처리하는 작업에 대해 우리가 정확히 동일한 기능을 필요로하는 것으로 나타났습니다. 몇몇 테스트는 임의로 길어질 수있는 사용자 코드의 실행으로 인해 시간의 미끄러짐을 에뮬레이션하는 결정 론적 방법을 필요로했습니다 (OnNext 핸들러를 Observable.Interval과 같이 생각하십시오).

희망이 도움이됩니다. 앞으로 몇 주 내에 Rx v2.0 RC 출시를 위해 계속 지켜봐주십시오!

-Bart (Rx 팀)

+0

감사합니다. Bart! 나는 그 반응에 감사한다. –

관련 문제