この議論 によると、次の2つの方法に違いはありません。
public async Task Foo()
{
await DoSomethingAsync();
}
public Task Foo()
{
return DoSomethingAsync();
}
実際、非常に単純なメソッドの場合、オーバーヘッドがいくらか除去されるため、呼び出しwithout async/awaitキーワードが優先されるように思われます。
ただし、これはユニットテストで常に機能するとは限りません。
MSTest
[TestClass]
public class AsyncTest
{
[TestMethod]
public async Task Test1()
{
await Task.Delay(0);
}
[TestMethod]
public Task Test2()
{
return Task.Delay(0);
}
}
NUnit
[TestFixture]
public class AsyncTest
{
[Test]
public async Task Test1()
{
await Task.Delay(0);
}
[Test]
public Task Test2()
{
return Task.Delay(0);
}
}
XUnit
public class AsyncTest
{
[Fact]
public async Task Test1()
{
await Task.Delay(0);
}
[Fact]
public Task Test2()
{
return Task.Delay(0);
}
}
Test1
パス。Test2
はテストランナーに表示されますが、実行されません。NUnitでは、Test2
は無視され、次のメッセージが表示されます。
テストメソッドの戻り値の型はvoidではありませんが、結果は期待できません
XUnitでは、Test2
パス。
すべての場合にタスクがまだ待機しているので、NUnitおよびMSTestテストランナーに影響を与えるasync
キーワードについてはどうでしょうか。おそらくいくつかの反射の問題?
これらのテストランナーは、リフレクションを使用して、Task
を返すメソッドが本当に非同期メソッドであるかどうかを確認しているようです。これは、メソッドが実行された場合異なる動作をするという意味ではありません-しかし、実行されていないだけです。
それはそれを言っているようなものです:
public string Name { get; set; }
と同等です:
private string name;
public Name { get { return name; } set { name = value; } }
動作に関しては論理的には同じですが、リフレクションで十分に努力すれば、違いがわかります。この特定のケースでは、他にも微妙な違いがありますが、同じ一般原則が適用されます。
現在のNUnitコード(この記事の執筆時点)では、検出は AsyncInvocationRegion.cs
。
確かに、非同期メソッドを使用せずにTask
を返す単体テストを作成することは少なくとも珍しいですが、不可能にはほど遠いです。