2014-09-05 2 views
1

뷰 모델에 대한 단위 테스트를 작성하고 있습니다. 이 응용 프로그램은 MVVM 지원을 위해 Caliburn.Micro를 사용하여 작성됩니다. 많은 뷰 모델은 Application.Current.Dispatcher에 의존하여 UI 스레드에 일부 코드를 전달합니다. 불행하게도, 첫 번째 통화를Application.Current.Dispatcher에 매달려 있습니다. 단위 테스팅을 할 때의 액션 (동작)

[ClassInitialize] 
    public static void InitClass(TestContext ctx) { 
     AppInitializer.InitApp(); 
    } 

: 이제

public class AppInitializer { 
    private static Application app; 
    public static void InitApp() { 
     app = app ?? (app = Application.Current ?? new Application()); 
    } 
} 

난 그냥 각 테스트 클래스에서 다음을 수행하십시오 테스트에서 내가 작성한에서

은 다음 클래스를 응용 프로그램 개체를 만들려면 보기 모델 내에서 Application.Current.Dispatcher로 이동하면 시간 제한에 도달 할 때까지 테스트가 중단됩니다.

저는 어떻게 든 Application.CurrentDispatcher를 추상화하고 싶지 않습니다. 뷰 모델에 좀 더 조롱 된 객체를 전달하고 싶지는 않습니다. 가능한 경우 해결 방법을 원합니다.

답변

3

Application.Run에 대한 전화가 누락되었습니다. 당신은 Application 클래스의 책임 중 하나가 현재 실행중인 스레드에서 Dispatcher을 만들고 시작하는 것이지만이 모든 것은 Run 호출 중에 발생합니다.

여기가 문제가되는 곳입니다. Run은 차단 호출입니다. 즉, Run이 종료 될 때까지 단위 테스트가 실행되지 않습니다. Store Apps에는 UITestMethod이라는 특수 속성이 있지만 WPF에서 사용할 수 없다고 생각합니다 (특히 MSTest를 사용하지 않는 경우).

그럼 선택할 수있는 옵션은 무엇입니까? 단위 테스트를 실행하는 스레드와 다른 스레드에서 응용 프로그램을 만들 수 있습니다. 그러나이 호출은 Join에 대한 메서드 호출을 가져 오며, 호출이 다른 스레드로 전달되었는지 확인해야합니다. 이것은 느린 단위 테스트의 가능성이 있습니다.

단위 테스트가 실행되는 스레드에서 디스패처를 수동으로 만들 수 없습니다. 이전에 App 클래스로 언급 한 것과 동일하기 때문에 Dispatcher.Run은 차단 호출입니다.

그래서 나는 Dispatcher에 대한 추상화를 작성하고 삽입하는 것이 좋습니다. 많은 고통을 덜어줍니다. 주변 상황에 대한

업데이트 : 코멘트에

, 나는 Dispatcher 추상화에 부합보기 모델에 객체를 주입에 의존하지 않는 솔루션으로 주위 상황을 언급했다.

public interface IDispatcher 
{ 
    void ExecuteOnUIThread(Action action); 
    // Add whatever methods you need on this interface 
} 

public static class DispatcherContext 
{ 
    // An instance that implements IDispatcher can be accessed via this static property 
    public static IDispatcher Dispatcher { get; set; } 
} 

// Of course you need to write an adapter for the WPF Dispatcher class 

이 방법은 당신이 당신의 단위 테스트에 대한 디스패처 모형을 만들 수 있지만 여전히보기 모델의 정적 속성을 통해이 액세스 할 수 있습니다 : 이것은 코드처럼 보일 것입니다 방법이다. 이 패턴에 대한 자세한 내용은 http://blogs.msdn.com/b/ploeh/archive/2007/07/23/ambientcontext.aspx 또는 Mark Seemann의 우수 서적 Dependency Injection in .NET에서 확인할 수 있습니다.

+0

app.Run()을 추가하면이 호출이 중단됩니다. – EngineerSpock

+0

미안하지만 아직 내 대답이 끝나지 않았습니다. 나는 그것을 업데이트했다. – feO2x

+0

흠, 불행히도 Caliburn의 정적 메서드 인 Execute.OnUITread (Action action)를 사용합니다. 그것은 모의하기가 어렵습니다. – EngineerSpock

관련 문제