1. ホーム
  2. c#

[解決済み] ユニットテストのためのAsync Voidメソッド呼び出しの待ち時間

2023-06-27 01:45:31

質問

以下のようなメソッドを持っています。

private async void DoStuff(long idToLookUp)
{
    IOrder order = await orderService.LookUpIdAsync(idToLookUp);   

    // Close the search
    IsSearchShowing = false;
}    

//Other stuff in case you want to see it
public DelegateCommand<long> DoLookupCommand{ get; set; }
ViewModel()
{
     DoLookupCommand= new DelegateCommand<long>(DoStuff);
}    

こんな感じでユニットテストをしようとしています。

[TestMethod]
public void TestDoStuff()
{
    //+ Arrange
    myViewModel.IsSearchShowing = true;

    // container is my Unity container and it setup in the init method.
    container.Resolve<IOrderService>().Returns(orderService);
    orderService = Substitute.For<IOrderService>();
    orderService.LookUpIdAsync(Arg.Any<long>())
                .Returns(new Task<IOrder>(() => null));

    //+ Act
    myViewModel.DoLookupCommand.Execute(0);

    //+ Assert
    myViewModel.IsSearchShowing.Should().BeFalse();
}

私のアサートは、モックアップのLookUpIdAsyncが完了する前に呼び出されます。 私の通常のコードでは、それは私が望むものです。 しかし、私のユニットテストでは、私はそれを望んでいません。

私はBackgroundWorkerを使用していたのをAsync/Awaitに変換しています。 バックグラウンドワーカーを使用すると、BackgroundWorkerが終了するのを待つことができるので、これは正しく機能していました。

しかし、async voidメソッドを待つ方法はないようです...。

このメソッドをどのようにユニットテストすればよいですか?

どのように解決するのですか?

単体テストをするための方法を考えました。

[TestMethod]
public void TestDoStuff()
{
    //+ Arrange
    myViewModel.IsSearchShowing = true;

    // container is my Unity container and it setup in the init method.
    container.Resolve<IOrderService>().Returns(orderService);
    orderService = Substitute.For<IOrderService>();

    var lookupTask = Task<IOrder>.Factory.StartNew(() =>
                                  {
                                      return new Order();
                                  });

    orderService.LookUpIdAsync(Arg.Any<long>()).Returns(lookupTask);

    //+ Act
    myViewModel.DoLookupCommand.Execute(0);
    lookupTask.Wait();

    //+ Assert
    myViewModel.IsSearchShowing.Should().BeFalse();
}

ここで重要なのは、私はユニットテストをしているので、非同期呼び出し(async voidの中)が返すようにしたいタスクに置き換えることができるということです。 そして、私は次に進む前にタスクが完了したことを確認するだけです。