20210730のC#に関する記事は2件です。

【C#】ユニットテストでMockを作るとUnsupported expression:~となった際の対策法。

はじめに ASP.NET Core C# + NUnitで開発をしていた際にユニットテストで詰まった部分について備忘録として残しておきます。 ユニットテストでアプリ側のクラスを生成し、コンストラクタ引数をモックで作成してテストをした際に「System.NotSupportedException : Unsupported expression:~Non-overridable members (here: ~~) may not be used in setup」というエラーが出てしまいました。 今回はその解決方法を2つほど記載していこうと思います。 サンプルコード アプリ側が以下のコードになっている場合を考えてみましょう。 利用しているのはASP.NET Core コンソールアプリです(簡略化のためProgram.csのMain関数は省略しています)。 appSettings.jsonファイルから「Test1」キーの値を引っ張ってきてその値が9999だったら0を返却し、そうでない場合は1を返却するというプログラムです。 program.cs public class TestClass : ConsoleAppBase { private readonly TestConfig _testConfig; public TestClass(IOptions<TestConfig> options) { _testConfig = options.Value; } [Command("test")] public void Test1() { Console.WriteLine(WriteNumber()); } public int WriteNumber() { if(_testConfig.Test1 == 9999) { return 0; } else { return 1; } } } TestConfig.cs namespace ConsoleApp2 { public class TestConfig { public int Test1 { get; set; } } } テストコードは以下のように作成してみました。 UnitTest1.cs [Test] public void WriteNumberMethodTest() { var testConfigMock = new Mock<IOptions<TestConfig>>(); testConfigMock.Setup(o => o.Value.Test1).Returns(9999); var target = new TestClass(testConfigMock.Object); // appSettings.jsonのTest1キーが9999時は0が返却される Assert.AreEqual(0, target.WriteNumber()); testConfigMock.Setup(o => o.Value.Test1).Returns(9998); var target2 = new TestClass(testConfigMock.Object); // appSettings.jsonのTest1キーが9999以外の時は1が返却される Assert.AreEqual(1, target.WriteNumber()); } コンソールアプリ自体は正常に動作しますがユニットテストでは最初に記載した通りエラーが出てしまいます。 エラーの原因 色々と調べていると世界には同じ内容で詰まっている方がいるものです。 Moq開発メンバーが回答してくれていますが、どうやらMoqはvirtualメソッドは実行されないようです。 (インターフェースを対象とすればオーバーライドの心配はしなくても大丈夫です。) そこで元のコードを見ると、確かに・・・Test1はvirtualになっていないですね・・・ virtual修飾子を付けてみる そこでvirtual修飾子を付けてみましょう。 TestConfig.cs namespace ConsoleApp2 { public class TestConfig { public virtual int Test1 { get; set; } } } テストを実行~~~ しっかりテストが通ったのが確認できましたね! もう1つの解決方法 こちらは公式ではないですが、stackoverflowで以下のような回答がありました。 Options.Createについて調べてみたら単純に自身のインスタンスをOptionsの型で返すようです。 こちらだとMoqを使用していないので先ほどのようにvirtualを付ける必要もないので良さげです。 どちらが良いのかは・・・ちょっと分かりませんが好みという感じなんですかね?? おわりに 記事を書きながらMoqやOptionsについて調べているといかに自分が雰囲気でそれらを使っていたかが分かります。 なかなか実務の時間にじっくり深堀りする余裕がないので仕方ないといえば仕方ないのですがその分しっかり自学でカバーしていきたいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【C#】ユニットテストでMockを作るとUnsupported expression:~Non-overridable membersとなった際の対策法。

はじめに ASP.NET Core C# + NUnitで開発をしていた際にユニットテストで詰まった部分について備忘録として残しておきます。 ユニットテストでアプリ側のクラスを生成し、コンストラクタ引数をモックで作成してテストをした際に「System.NotSupportedException : Unsupported expression:~Non-overridable members (here: ~~) may not be used in setup」というエラーが出てしまいました。 今回はその解決方法を2つほど記載していこうと思います。 サンプルコード アプリ側が以下のコードになっている場合を考えてみましょう。 利用しているのはASP.NET Core コンソールアプリです(簡略化のためProgram.csのMain関数は省略しています)。 appSettings.jsonファイルから「Test1」キーの値を引っ張ってきてその値が9999だったら0を返却し、そうでない場合は1を返却するというプログラムです。 program.cs public class TestClass : ConsoleAppBase { private readonly TestConfig _testConfig; public TestClass(IOptions<TestConfig> options) { _testConfig = options.Value; } [Command("test")] public void Test1() { Console.WriteLine(WriteNumber()); } public int WriteNumber() { if(_testConfig.Test1 == 9999) { return 0; } else { return 1; } } } TestConfig.cs namespace ConsoleApp2 { public class TestConfig { public int Test1 { get; set; } } } テストコードは以下のように作成してみました。 UnitTest1.cs [Test] public void WriteNumberMethodTest() { var testConfigMock = new Mock<IOptions<TestConfig>>(); testConfigMock.Setup(o => o.Value.Test1).Returns(9999); var target = new TestClass(testConfigMock.Object); // appSettings.jsonのTest1キーが9999時は0が返却される Assert.AreEqual(0, target.WriteNumber()); testConfigMock.Setup(o => o.Value.Test1).Returns(9998); var target2 = new TestClass(testConfigMock.Object); // appSettings.jsonのTest1キーが9999以外の時は1が返却される Assert.AreEqual(1, target.WriteNumber()); } コンソールアプリ自体は正常に動作しますがユニットテストでは最初に記載した通りエラーが出てしまいます。 エラーの原因 色々と調べていると世界には同じ内容で詰まっている方がいるものです。 Moq開発メンバーが回答してくれていますが、どうやらMoqはvirtualを付ける必要があるようです。 (インターフェースを対象とすればオーバーライドの心配はしなくても大丈夫です。) そこで元のコードを見ると、確かに・・・Test1はvirtualになっていないですね・・・ virtual修飾子を付けてみる そこでvirtual修飾子を付けてみましょう。 TestConfig.cs namespace ConsoleApp2 { public class TestConfig { public virtual int Test1 { get; set; } } } テストを実行~~~ しっかりテストが通ったのが確認できましたね! もう1つの解決方法 こちらは公式ではないですが、stackoverflowで以下のような回答がありました。 Options.Createについて調べてみたら単純に自身のインスタンスをOptionsの型で返すようです。 こちらだとMoqを使用していないので先ほどのようにvirtualを付ける必要もないので良さげです。 どちらが良いのかは・・・ちょっと分かりませんが好みという感じなんですかね?? おわりに 記事を書きながらMoqやOptionsについて調べているといかに自分が雰囲気でそれらを使っていたかが分かります。 なかなか実務の時間にじっくり深堀りする余裕がないので仕方ないといえば仕方ないのですがその分しっかり自学でカバーしていきたいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む