はじめに
今回はUnity Test Frameworkでエラーのテストをする方法について紹介したいと思います。
Assert.Throws
Assert.Throws
を利用することで特定の例外がスローされることをチェックすることができます。
The Assert.Throws method is pretty much in a class by itself. Rather than comparing values, it attempts to invoke a code snippet, represented as a delegate, in order to verify that it throws a particular exception.
It's also in a class by itself in that it returns an Exception, rather than void, if the Assert is successful. See the example below for a few ways to use this.
// DeepL翻訳
Assert.Throwsメソッドは、それだけで一つのクラスになっている。値を比較するのではなく、デリゲートとして表現されたコード・スニペットを呼び出して、それが特定の例外をスローするかどうかを検証しようとします。
また、Assert が成功した場合は void ではなく Exception を返すという点でも、それ自体がひとつのクラスになっています。これを使用するいくつかの方法については、以下の例を参照してください。
基本的な使い方は以下の通り。
[Test] public static void Hoge() { // ジェネリックを利用したタイプ(個人的にこっちの方が使いやすいと思う) Assert.Throws<NotImplementedException>(() => { // NotImplementedExceptionをスローするコードが記述されていればPass, それ以外はFail throw new NotImplementedException(); }); // ジェネリックを利用しないタイプ var exception = Assert.Throws(typeof(NotImplementedException), () => { // NotImplementedExceptionをスローするコードが記述されていればPass, それ以外はFail throw new NotImplementedException(); }); // System.NotImplementedException Debug.Log(exception.GetType()); }
また非同期用のAssert.ThrowAsync
が用意されているのですが、現状のUnityですと正しく動作しないので注意です。
Assert.ThrowsAsync<NotImplementedException>(async () => { // NotImplementedExceptionをスローするコードが記述されていればPass, それ以外はFail await Task.Delay(1); throw new NotImplementedException(); });
Assert.Catch
Assert.Throws
の場合は指定した例外の型が同じでないとダメでしたが、Assert.Catch
を利用すると派生型も許容するようになります。
// 派生方も許容する場合はCatchを利用する, ジェネリックを利用したタイプ Assert.Catch<Exception>(() => { // TActual型(ここではException)+その派生型をスローするコードが記述されていればPass, それ以外はFail throw new NotImplementedException(); }); var exception2 = Assert.Catch(typeof(Exception), () => { // TActual型(ここではException)+その派生型をスローするコードが記述されていればPass, それ以外はFail throw new NotImplementedException(); }); // System.NotImplementedException Debug.Log(exception2);
Assert.Thatを利用する
上記の2種類で事足りるのですが、Assert.That
をなるべく使って欲しいという方もいらっしゃるのでAssert.That
を利用した方法も紹介します。
// Assert.ThrowsのAssert.Thatを利用したバージョン Assert.That(() => { // NotImplementedExceptionをスローするコードが記述されていればPass, それ以外はFail throw new NotImplementedException(); }, Throws.TypeOf<NotImplementedException>()); // Assert.CatchのAssert.Thatを利用したバージョン Assert.That(() => { // NotImplementedExceptionをスローするコードが記述されていればPass, それ以外はFail throw new NotImplementedException(); }, Throws.InstanceOf<Exception>());
小ネタ
特定の型の例外かどうかを調べるだけでなく、メッセージが等しいかなどの制約を加えたりもできます。
Assert.That(() => { // NotImplementedExceptionをスローするコードが記述されていればPass, それ以外はFail throw new NotImplementedException("Hoge"); }, Throws.TypeOf<NotImplementedException>().And.Message.EqualTo("Hoge") );