【.NET Core】MoqのQuickstartをやってみる(Matching Arguments)
テストプロジェクトにパッケージ参照追加
$ dotnet add package moq
テストプロジェクトファイルの中身を見てみるとMoqが追記されました。
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170628-02" /> <PackageReference Include="moq" Version="4.7.137" /> <PackageReference Include="MSTest.TestAdapter" Version="1.1.18" /> <PackageReference Include="MSTest.TestFramework" Version="1.1.18" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\PrimeService\PrimeService.csproj" /> </ItemGroup> </Project>
ベースになるインターフェイスとクラスの作成
■MoqQuickstart.cs
namespace MoqQuickstart { public interface IFoo { Bar Bar { get; set; } string Name { get; set; } int Value { get; set; } bool DoSomething(string value); bool DoSomething(int number, string value); string DoSomethingStringy(string value); bool TryParse(string value, out string outputValue); bool Submit(ref Bar bar); int GetCount(); bool Add(int value); } public class Bar { public virtual Baz Baz { get; set; } public virtual bool Submit() { return false; } } public class Baz { public virtual string Name { get; set; } } }
テストプロジェクトにテストクラスを作成
■MatchingArguments.cs
using System; using System.Text.RegularExpressions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using MoqQuickstart; namespace MoqQuickstart.Tests { [TestClass] public class MatchingArguments { [TestMethod] public void any_value() { var mock = new Mock<IFoo>(); mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(true); var f = mock.Object; var actual = f.DoSomething("hoge"); Assert.IsTrue(actual); } [DataTestMethod] [DataRow(-1)] [DataRow(1)] [DataRow(3)] public void matching_Func_int_lazy_evaluated(int value) { var mock = new Mock<IFoo>(); mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true); var f = mock.Object; var actual = f.Add(value); Assert.IsFalse(actual, $"{value} has a remainder of 0"); } [DataTestMethod] [DataRow(-1)] [DataRow(11)] public void matching_ranges(int value) { var mock = new Mock<IFoo>(); mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true); var f = mock.Object; var actual = f.Add(value); Assert.IsFalse(actual, $"{value} is in range"); } [DataTestMethod] [DataRow("a")] [DataRow("A")] [DataRow("hack")] public void matching_regex(string value) { var mock = new Mock<IFoo>(); mock.Setup(x => x.DoSomethingStringy(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo"); var f = mock.Object; var actual = f.DoSomethingStringy(value); Assert.AreEqual("foo", actual); } } }
指定したフルネームでテストを実行
メソッド名まで指定しないとダメっぽい。メソッド単位でテストしたいときに。
$ dotnet test --filter "FullyQualifiedName=MoqQuickstart.Tests.MatchingArguments.any_value" 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. テスト実行を開始しています。お待ちください... テストの合計数: 1。成功: 1。失敗:0。スキップ: 0。 テストの実行に成功しました。 テスト実行時間: 2.6119 秒
指定した名前を含むテストを実行
クラス単位で指定してみます。名前空間単位でも指定できたのでお好みの範囲で。
$ dotnet test --filter "FullyQualifiedName~MoqQuickstart.Tests.MatchingArguments" 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. テスト実行を開始しています。お待ちください... テストの合計数: 9。成功: 9。失敗:0。スキップ: 0。 テストの実行に成功しました。 テスト実行時間: 3.3198 秒
今までIt.IsAny
メソッド一本槍でした(足軽感)。