2016-08-17 6 views
1

I는 다음의 기능MVVM 광 디스패처 단위 테스트

public void Reset() 
{ 
    DisableModule(); 
    DispatcherHelper.UIDispatcher.Invoke(() => 
    { 
      PixelPointInfoCollection.Clear(); 
      PixelPointInfoCollection.Add(new PointViewModel()); 
    }); 
    _cachedPoints.Clear(); 
} 

단위 테스트를 실행할 때 다음의 코드는 상기()를 호출 방법에 끼었을 갖는다.

디스패처에서 맞춤 인터페이스를 만들고 유닛 테스트에서 디스패처를 조롱하는 방법에 대한 기사를 보았습니다. 예 : http://blog.zuehlke.com/en/mvvm-and-unit-testing/

다른 방법이 있습니까? 커다란 코드 기반이 있습니다. 지금 모든 것을 바꿀 필요가 있습니까?

업데이트 지금 여기 들어 2016년 8월 18일 내가 무슨 짓을 그리고 그것은 App.xaml.cs를 내가 전화 AppServices.Init (새 DispatcherWrapper()) 안에 너무

public static class AppServices 
{ 

    public static IDispatcher Dispatcher { get; set; } 
    public static void Init(IDispatcher dispatcher) 
    { 
     Dispatcher = dispatcher; 
    } 
} 

//this inteface is in order to overrcome MVVM light Dispatcher so we can mock it for unit tests 
public interface IDispatcher 
{ 
    void Invoke(Action action); 
    void Invoke(Action action, DispatcherPriority priority); 
    DispatcherOperation BeginInvoke(Action action); 
} 

public class DispatcherWrapper :IDispatcher 
{ 
    public DispatcherWrapper() 
    { 
     DispatcherHelper.Initialize(); 
    } 
    public void Invoke(Action action) 
    { 
     DispatcherHelper.UIDispatcher.Invoke(action); 
    } 

    public void Invoke(Action action, DispatcherPriority priority) 
    { 
     DispatcherHelper.UIDispatcher.Invoke(action, priority); 
    } 

    public DispatcherOperation BeginInvoke(Action action) 
    { 
     return DispatcherHelper.UIDispatcher.BeginInvoke(action); 
    } 
} 

을하고있다;

단위 테스트에서 나는 을 호출합니다. AppServices.Init (Substitute.For()); 당신이 일이 내가 뭔가를 누락하는 경우 의견을주십시오

NSubstitute

를 사용

, 나는 내가

DispatcherHelper.UIDispatcher.Invoke 
+0

불행히도 예. 귀하의 상황은 초기 설계 문제로 인해 단위 테스트에 코드 기반을 어렵게 만듭니다. 코드에 대한 단위 테스트를 만드는 것이 어렵다는 것은 코드가 얼마나 잘 설계되었는지와 직접 관련이 있습니다. 게시자가 게시물에서 언급 한 기사는 발송자 액세스를 모의 할 수 있도록하기 위해 수행해야하는 작업입니다. 발송자는 단위 테스트 중에 사용할 수없는 UI 스레드와 관련된 구현 문제입니다. 따라서 'Invoke'에 대한 잠금 – Nkosi

답변

1

내에서 수행하는 데 사용 나는이 작업을 실행하는 조롱 프레임 워크를 만들 수 있죠 방법에 대한 걱정 불행하게도 초기 설계 문제로 인해 코드 테스트가 단위 테스트에 어려움을 겪었습니다. 코드에 대한 단위 테스트를 만드는 것이 어렵다는 것은 코드가 얼마나 잘 설계되었는지와 직접 관련이 있습니다. 게시자가 게시물에서 언급 한 기사는 발송자 액세스를 모의 할 수 있도록하기 위해 수행해야하는 작업입니다. 발송자는 단위 테스트 중에 사용할 수없는 UI 스레드와 관련된 구현 문제입니다. 따라서 Invoke

의 잠금은 당신이 언급 한 기사 인용 :

우리는 App.Current.Dispatcher를 사용하는 코드를 테스트 할 수 없습니다를 ( App.Current는 동안 null 될 것이기 때문에 단위 테스트 실행).

가능한 용액 인터페이스 IDispatcher 및 래퍼 그 인터페이스를 구현 주위 App.Current.Dispatcher를 작성하는 것이다.

public interface IDispatcher { 
    void Invoke(Action action); 
    void BeginInvoke(Action action); 
} 

public class DispatcherWrapper : IDispatcher { 
    Dispatcher dispatcher; 

    public DispatcherWrapper() {  
     dispatcher = Application.Current.Dispatcher;   
    } 
    public void Invoke(Action action) { 
     dispatcher.Invoke(action); 
    } 

    public void BeginInvoke(Action action) { 
     dispatcher.BeginInvoke(action); 
    } 
} 
+0

보기 모델 코드는 스레드 별 실행을 런타임에 삽입 된 SynchronizationContext 구현으로 위임해야합니다.UI에서 DispatcherSynchronizationContext를 사용할 수 있으며 테스트에서 현재 스레드에서 모든 것을 동시에 실행하는 구현을 해킹 할 수 있습니다. – Will

+0

@Will 예를 들어 답을 해 주시겠습니까? – Gilad

+0

@Gilad 본질적으로 Dispatcher 대신 SynchronizationContext를 사용하므로 메서드 이름이 달라집니다. 그것은 그렇게 복잡하지 않습니다. – Will