【.NET Core】MoqのQuickstartをやってみる(Miscellaneous)
概要
Miscellaneousってなんだろう?と思って調べたら「その他」とか「雑多な」とかって意味らしい。略してmisc。
テストコード
呼び出し回数に応じて戻り値や例外投げる方法とprotectedメンバーのセットアップについてですね。思ってたより雑多感はない。
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Moq.Protected; using MoqQuickstart; namespace MoqQuickstart.Tests { [TestClass] public class Miscellaneous { [TestMethod] public void setting_up_a_member_to_return_different_values_throw_exceptions_on_sequential_calls(){ var mock = new Mock<IFoo>(); mock.SetupSequence(f => f.GetCount()) .Returns(3) // will be returned on 1st invocation .Returns(2) // will be returned on 2nd invocation .Returns(1) // will be returned on 3rd invocation .Returns(0) // will be returned on 4th invocation .Throws(new InvalidOperationException()); // will be thrown on 5th invocation var foo = mock.Object; var first = foo.GetCount(); var second = foo.GetCount(); var third = foo.GetCount(); var fourth = foo.GetCount(); Assert.AreEqual(3,first); Assert.AreEqual(2,second); Assert.AreEqual(1,third); Assert.AreEqual(0,fourth); try { var fifth = foo.GetCount(); Assert.Fail(); } catch(InvalidOperationException) { Assert.IsTrue(true); } } [TestMethod] public void setting_expectations_for_protected_members() { var mock = new Mock<CommandBase>(); mock.Protected() .Setup<int>("Execute") .Returns(5); mock.Protected() .Setup<string>("Execute", ItExpr.IsAny<string>()) .Returns("foo"); Assert.AreEqual(5, mock.Object.Processing()); Assert.AreEqual("foo", mock.Object.Processed("bar")); } } }
QuickstartのページにはCommandBase
クラスの記述がないので、これも追加で。
using System; namespace MoqQuickstart { public class CommandBase { public int Processing() { return Execute(); } public string Processed(string s) { return Execute(s); } protected virtual int Execute() { return 0; } protected virtual string Execute(string s) { return "fix:" + s; } } }
テストを実行してみましょう。
$ dotnet test --filter "FullyQualifiedName~MoqQuickstart.Tests.Miscellaneous" Build started, please wait... Build completed. Test run for /Users/soil/src/github/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/netcoreapp2.0/PrimeService.Tests.dll(.NETCoreApp,Version=v2.0) Microsoft (R) Test Execution Command Line Tool Version 15.3.0-preview-20170628-02 Copyright (c) Microsoft Corporation. All rights reserved. テスト実行を開始しています。お待ちください... テストの合計数: 2。成功: 2。失敗:0。スキップ: 0。 テストの実行に成功しました。 テスト実行時間: 2.8108 秒
ミスレニアス?ミセレイニアス?
Miscellaneousでしょう。
【.NET Core】MoqのQuickstartをやってみる(Verification)
概要
MoqのQuickstartをやってみる。今回はVerify
メソッドです。
テストコード
こんな感じかなぁ。
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using MoqQuickstart; namespace MoqQuickstart.Tests { [TestClass] public class Verification { [TestMethod] public void verify() { var mock = new Mock<IFoo>(); mock.Object.DoSomething("ping"); mock.Verify(foo => foo.DoSomething("ping")); } [TestMethod] public void verify_with_custom_error_message_for_failure() { var mock = new Mock<IFoo>(); mock.Verify(foo => foo.DoSomething("ping"), "When doing operation X, the service should be pinged always"); } [TestMethod] public void method_should_never_be_called() { var mock = new Mock<IFoo>(); mock.Verify(foo => foo.DoSomething("ping"), Times.Never()); } [TestMethod] public void called_at_least_once() { var mock = new Mock<IFoo>(); mock.Object.DoSomething("ping"); mock.Verify(foo => foo.DoSomething("ping"), Times.AtLeastOnce()); } [TestMethod] public void verify_getter_invocation_regardless_of_value() { var mock = new Mock<IFoo>(); var name = mock.Object.Name; mock.VerifyGet(foo => foo.Name); } [TestMethod] public void verify_setter_invocation_regardless_of_value() { var mock = new Mock<IFoo>(); mock.Object.Name = "foo"; mock.VerifySet(foo => foo.Name); } [TestMethod] public void verify_setter_called_with_specific_value() { var mock = new Mock<IFoo>(); mock.Object.Name = "foo"; mock.VerifySet(foo => foo.Name ="foo"); } [DataTestMethod] [DataRow(1)] [DataRow(3)] [DataRow(5)] public void verify_setter_with_an_argument_matcher(int value) { var mock = new Mock<IFoo>(); mock.Object.Value = value; mock.VerifySet(foo => foo.Value = It.IsInRange(1, 5, Range.Inclusive)); } } }
テストを実行してみましょう。
verify_with_custom_error_message_for_failure
でちゃんとエラーメッセージも表示されていますね!
$ dotnet test --filter "FullyQualifiedName~MoqQuickstart.Tests.Verification" Build started, please wait... Build completed. Test run for /Users/soil/src/github/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/netcoreapp2.0/PrimeService.Tests.dll(.NETCoreApp,Version=v2.0) Microsoft (R) Test Execution Command Line Tool Version 15.3.0-preview-20170628-02 Copyright (c) Microsoft Corporation. All rights reserved. テスト実行を開始しています。お待ちください... 失敗 MoqQuickstart.Tests.Verification.verify_with_custom_error_message_for_failure エラー メッセージ: Test method MoqQuickstart.Tests.Verification.verify_with_custom_error_message_for_failure threw exception: Moq.MockException: When doing operation X, the service should be pinged always Expected invocation on the mock at least once, but was never performed: foo => foo.DoSomething("ping") No setups configured. No invocations performed. スタック トレース: at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable`1 setups, IEnumerable`1 actualCalls, Expression expression, Times times, Int32 callCount) at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times) at Moq.Mock.Verify[T,TResult](Mock`1 mock, Expression`1 expression, Times times, String failMessage) at Moq.Mock`1.Verify[TResult](Expression`1 expression, String failMessage) at MoqQuickstart.Tests.Verification.verify_with_custom_error_message_for_failure() in /Users/soil/src/github/unit-testing-using-dotnet-test/PrimeService.Tests/Verification.cs:line 23 テストの合計数: 10。成功: 9。失敗:1。スキップ: 0。 テストの実行に失敗しました。 テスト実行時間: 2.3554 秒
はい、次!
【.NET Core】MoqのQuickstartをやってみる(Callbacks)
概要
MoqのQuickstartをやってみる。Callback
メソッドについてです。
テストコード
Callback
メソッドの使い方に関しては特に何もないですね。そのまま使えばいいと思うmo(^q^)
using System; using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using MoqQuickstart; namespace MoqQuickstart.Tests { [TestClass] public class Callbacks { [TestMethod] public void callback() { var expected = 2; var mock = new Mock<IFoo>(); var calls = 0; mock.Setup(foo => foo.DoSomething("ping")) .Returns(true) .Callback(() => calls++); var f = mock.Object; f.DoSomething("ping"); f.DoSomething("pong"); f.DoSomething("ping"); Assert.AreEqual(expected, calls); } [TestMethod] public void access_invocation_arguments() { var expected = new List<string>(){"foo", "bar", "baz"}; var mock = new Mock<IFoo>(); var callArgs = new List<string>(); mock.Setup(foo => foo.DoSomething(It.IsAny<string>())) .Returns(true) .Callback((string s) => callArgs.Add(s)); var f = mock.Object; f.DoSomething("foo"); f.DoSomething("bar"); f.DoSomething("baz"); CollectionAssert.AreEqual(expected, callArgs); } [TestMethod] public void calalternate_equivalent_generic_method_syntax() { var expected = new List<string>(){"foo", "bar", "baz"}; var mock = new Mock<IFoo>(); var callArgs = new List<string>(); mock.Setup(foo => foo.DoSomething(It.IsAny<string>())) .Returns(true) .Callback<string>(s => callArgs.Add(s)); var f = mock.Object; f.DoSomething("foo"); f.DoSomething("bar"); f.DoSomething("baz"); CollectionAssert.AreEqual(expected, callArgs); } [TestMethod] public void access_arguments_for_methods_with_multiple_parameters() { var expected = new List<string>(){"foo", "bar", "baz"}; var mock = new Mock<IFoo>(); var callArgs = new List<string>(); mock.Setup(foo => foo.DoSomething(It.IsAny<int>(), It.IsAny<string>())) .Returns(true) .Callback<int, string>((i, s) => callArgs.Add(s)); var f = mock.Object; f.DoSomething(1, "foo"); f.DoSomething(2, "bar"); f.DoSomething(3, "baz"); CollectionAssert.AreEqual(expected, callArgs); } [TestMethod] public void callbacks_can_be_specified_before_and_after_invocation() { var mock = new Mock<IFoo>(); mock.Setup(foo => foo.DoSomething("ping")) .Callback(() => Console.WriteLine("Before returns")) .Returns(true) .Callback(() => Console.WriteLine("After returns")); var actual = mock.Object.DoSomething("ping"); Assert.IsFalse(actual); } } }
テストを実行してみましょう。callbacks_can_be_specified_before_and_after_invocation
はテスト失敗時に標準出力メッセージが確認できますね。
$ dotnet test --filter "FullyQualifiedName~MoqQuickstart.Tests.Callbacks" Build started, please wait... Build completed. Test run for /Users/soil/src/github/unit-testing-using-dotnet-test/PrimeService.Tests/bin/Debug/netcoreapp2.0/PrimeService.Tests.dll(.NETCoreApp,Version=v2.0) Microsoft (R) Test Execution Command Line Tool Version 15.3.0-preview-20170628-02 Copyright (c) Microsoft Corporation. All rights reserved. テスト実行を開始しています。お待ちください... 失敗 MoqQuickstart.Tests.Callbacks.callbacks_can_be_specified_before_and_after_invocation エラー メッセージ: Assert.IsFalse failed. スタック トレース: at MoqQuickstart.Tests.Callbacks.callbacks_can_be_specified_before_and_after_invocation() in /Users/soil/src/github/unit-testing-using-dotnet-test/PrimeService.Tests/Callbacks.cs:line 100 標準出力メッセージ: Before returns After returns テストの合計数: 5。成功: 4。失敗:1。スキップ: 0。 テストの実行に失敗しました。 テスト実行時間: 2.4901 秒