2012-12-30 2 views
4

Visual Studio 2012와 동기화 컨텍스트가 필요한 비동기 테스트가 있습니다.
그러나 MSTest의 기본 동기화 컨텍스트는 null입니다.
동기화 컨텍스트가있는 WPF 또는 WinForms-UI 스레드에서 실행중인 것으로 테스트하고 싶습니다.
테스트 스레드에 SynchronizationContext를 추가하는 가장 좋은 방법은 무엇입니까?비동기 테스트 메서드에 동기화 컨텍스트를 추가하는 방법

[TestMethod] 
    public async Task MyTest() 
    { 
     Assert.IsNotNull(SynchronizationContext.Current); 
     await MyTestAsync(); 
     DoSomethingOnTheSameThread(); 
    } 

답변

5

,이 같은 내 testmethods을 작성할 수 있습니다

[TestMethod] 
    public void MyTest() 
    { 
     Helper.RunInWpfSyncContext(async() => 
     { 
     Assert.IsNotNull(SynchronizationContext.Current); 
     await MyTestAsync(); 
     DoSomethingOnTheSameThread(); 
     }); 
    } 

내부 코드는 이제 WPF 동기화 컨텍스트에서 실행 및 MSTEST에 사용되는 모든 예외를 처리합니다. 도우미 방법은 Stephen Toub 출신이다 :

using System.Windows.Threading; // WPF Dispatcher from assembly 'WindowsBase' 

public static void RunInWpfSyncContext(Func<Task> function) 
{ 
    if (function == null) throw new ArgumentNullException("function"); 
    var prevCtx = SynchronizationContext.Current; 
    try 
    { 
    var syncCtx = new DispatcherSynchronizationContext(); 
    SynchronizationContext.SetSynchronizationContext(syncCtx); 

    var task = function(); 
    if (task == null) throw new InvalidOperationException(); 

    var frame = new DispatcherFrame(); 
    var t2 = task.ContinueWith(x=>{frame.Continue = false;}, TaskScheduler.Default); 
    Dispatcher.PushFrame(frame); // execute all tasks until frame.Continue == false 

    task.GetAwaiter().GetResult(); // rethrow exception when task has failed 
    } 
    finally 
    { 
    SynchronizationContext.SetSynchronizationContext(prevCtx); 
    } 
} 
6

사용자 지정 SynchronizationContext에 파생 클래스를 생성하고 SynchronizationContext.SetSynchronizationContext와 현재 컨텍스트로 등록 할 수 있습니다. "Await, SynchronizationContext, and Console Apps"및 "Await, SynchronizationContext, and Console Apps: Part 2"에 대한 Stephen Toub의 게시물을 읽어보십시오.

사용자 지정 SynchronizationContext는 비동기 실행을위한 콜백을받는 Post 메서드 만 재정의해야합니다. 당신이 그들을 어떻게 수행 할 것인가는 당신에게 달렸습니다.

첫 번째 게시물은 게시 된 모든 작업을 대기열에 저장하고 차단 루프는 대기열에서 작업을 수행하고이를 단일 스레드에서 실행하는 동기화 컨텍스트를 제공합니다.

[TestMethod] 
public void MyTest() 
{ 
    AsyncContext.Run(async() => 
    { 
    Assert.IsNotNull(SynchronizationContext.Current); 
    await MyTestAsync(); 
    DoSomethingOnTheSameThread(); 
    }); 
} 

그러나이가하는가, 예를 들어, 특정 UI 환경을 완전히 가짜, Dispatcher.CurrentDispatcher 여전히 null 될 것 없습니다 :

6

당신은 단일 스레드 AsyncContext라고 내 AsyncEx librarySynchronizationContext를 사용할 수 있습니다. 그러한 위조 수준이 필요한 경우 원래 비동기 CTP의 SynchronizationContext 구현을 사용해야합니다. 테스트 용으로 사용할 수있는 세 개의 SynchronizationContext 구현품 (일반용 (내 AsyncContext과 유사), WinForms 용, WPF 용)이 함께 제공됩니다. 파나지오티스 Kanavos와 스티븐 클리어 리에서 정보를 사용

관련 문제