2016-08-17 10 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/

他に方法はありますか?私は巨大なコードベースを持っています。私は本当にすべてを今変更する必要がありますか?私は AppServices.Init(新DispatcherWrapper())を呼び出して今ここについては

アップデート2016年8月18日 は私がやったことであり、それはapp.xaml.cs の内側そう

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.Currentnull中となりますので、私たちは、App.Current.Dispatcherを(使用してコードをテストすることができませんユニットテストの実行)。

可能な解決策は、インターフェイス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

@ウィルあなたは例を挙げて完全な答えをくれますか? – Gilad

+0

@Giladこれは本質的にDispatcherの代わりにSynchronizationContextを使用しているため、メソッド名が異なります。それほど複雑ではありません。 – Will