0

MVVMプロジェクトでRxとRxUIを使用していて、WCFサービスからのデータを非同期でクエリするビューモデルがあります。単体テストでは、期待値を持つタスクを返すモックオブジェクトを作成します。

これが私のビューモデルがどのように見えるかの一般的な考え方です

public class ViewModel : ReactiveObject
{
    private IContext _context;

    public ViewModel(IContext context)
    {
        _context = context;

        Observable.FromAsync(() => _context.WcfServiceCall())
              .Subscribe(result => {
                   Children.AddRange(results.Select(r => new ChildViewModel(r).ToList()));
               });
     }

     public ObservableCollection<ChildViewModel> { get; private set;}
}

私の単体テストは次のようになります

[TestFixture]
public class ViewModelTest : AssertionHelper
{
    [Test]
    public void ShouldSetChildren()
    {
        var c = new Mock<IContext>();
        c.Setup(q => q.WcfServiceCall())
            .Returns(Task.Run(() => new []{ 1,2,3,4,5,6 })):

        var vm = new ViewModel(c.Object);
        var p = vm.Children.First(); // this call sometimes fails

        ... 
     }
}

私が抱えている問題は、この種のことを行う400以上のテストがあり、それらはすべてほとんどの場合機能しますが、シーケンスに値がないことを報告する、一度に1つか2つの失敗したテストをランダムに取得することです。これは予測不可能でランダムです。失敗した後、テストを再度実行して、すべて成功することができます。ここで説明するようにTestSchedulerを追加しましたが、問題は解決しません。

非同期メソッド呼び出しを行うメソッドをテストするためのより良い方法はありますか?

Paul Bettの入力から編集:FromAsyncはISchedulerパラメーターを受け取らないようですが、SubscribeOnとObserveOnを使用できます。

または、WCF非同期メソッドを直接呼び出して、返されたタスクを監視対象に変換することもできます。Observable.FromAsyncを使用する方が適切なのか、使用しない方が適切なのかがわかりません。

4

2 に答える 2

1

パラメータObservable.FromAsyncを取りますか?ISchedulerそれはあなたのテストスケジューラですか?

于 2013-01-15T23:45:37.790 に答える
0

私の単体テストは、あまりにも多くの可動部分に触れていたという点で間違っていたことに気付きました。モックされた Web サービス呼び出しが期待どおりに行われることを確認するテストがありますが、そのテスト ポイントに重点を置いていないテストにその複雑さを含めるべきではありません。

ビュー モデルに移動するときに、wcf サービスを呼び出しています。IScheduler の指定に関して小さな変更を加えた、私のビュー モデルのより良い表現を次に示します。

public class ViewModel : ReactiveObject, IRoutableViewModel
{
    private IContext _context;
    public ViewModel(IContext context)
    {
        _context = context;
        Weeks = new ReactiveCollection<WeekViewModel>();

        this.WhenNavigatedTo(() =>
        {
            _context.Service.GetWeeksAsync()
                .ToObservable()
                .ObserveOn(RxApp.DeferredScheduler)
                .Subscribe(result =>
                {
                    Weeks.AddRange(result.Select(w => WeekViewModel(w)));
                });
        });

        // ...
    }

    public ReactiveCollection<WeekViewModel> Weeks { get; private set; }
}

コンテキストを設定して Weeks コレクションを設定し、ルーターを使用して ViewModel に移動する代わりに、ユニット テストで Weeks コレクションにオブジェクトを追加し、ナビゲーションと非同期 Web サービス呼び出しをスキップしています。これにより、テストが少し減り、私が知る限り不安定性が解消され、テスト スイートの実行時間が短縮されました。

したがって、私の単体テストは次のようになります

[TestFixture]
public class ViewModelTest : AssertionHelper
{
    [Test]
    public void ShouldSetChildren()
    {
        var c = new Mock<IContext>();
        var vm = new ViewModel(c.Object);
        vm.Children.AddRange((new []{1,2,3,4,5,6}).Select(i => new ChildViewModel(i)));

        var p = vm.Children.First(); // this is valid now - no timing issues

        ... 
    }
}

コードはアプリでは正しく動作しますが、テスト ランナーでは問題があったため、当面の問題はこれで解決すると思います。

于 2013-01-16T19:11:40.493 に答える