本篇作為筆記用途,記錄 .NET Unit Test 參考資料
Test Execution Workflow 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 using Microsoft.VisualStudio.TestTools.UnitTesting;namespace MSTestUnitTests { [TestClass ] public class YourUnitTests { [AssemblyInitialize ] public static void AssemblyInit (TestContext context ) { } [ClassInitialize ] public static void TestFixtureSetup (TestContext context ) { } [TestInitialize ] public void Setup () { } [AssemblyCleanup ] public static void AssemblyCleanup () { } [ClassCleanup ] public static void TestFixtureTearDown () { } [TestCleanup ] public void TearDown () { } [TestMethod ] public void YouTestMethod () { } } }
Attributes
MSTest v2.x
NUnit
xUnit.net 2.x
說明
[TestMethod]
[Test]
[Fact]
標記測試方法
[TestClass]
[TestFixture]
n/a
標記測試班
[TestInitialize]
[SetUp]
Constructor
在每個測試用例之前觸發
[TestCleanup]
[TearDown]
IDisposable.Dispose
在每個測試用例之後觸發
[ClassInitialize]
[OneTimeSetUp]
IClassFixture
測試用例開始之前的一次性觸發方法
[ClassCleanup]
[OneTimeTearDown]
IClassFixture
測試用例結束後的一次性觸發方法
[Ignore]
[Ignore(“reason”)]
[Fact(Skip=”reason”)]
忽略測試用例
[TestProperty]
[Property]
[Trait]
在測試上設置任意元數據
[DataRow]
[Theory]
[Theory]
配置數據驅動的測試
[TestCategory(“”)]
[Category(“”)]
[Trait(“Category”, “”)]
對測試用例或類進行分類
Assertions 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 Assert.AreEqual(28 , _actualFuel); Assert.AreNotEqual(28 , _actualFuel); Assert.AreSame(_expectedRocket, _actualRocket); Assert.AreNotSame(_expectedRocket, _actualRocket); Assert.IsTrue(_isThereEnoughFuel); Assert.IsFalse(_isThereEnoughFuel); Assert.IsNull(_actualRocket); Assert.IsNotNull(_actualRocket); Assert.IsInstanceOfType(_actualRocket, typeof (Falcon9Rocket)); Assert.IsNotInstanceOfType(_actualRocket, typeof (Falcon9Rocket)); StringAssert.Contains(_expectedBellatrixTitle, "Bellatrix" ); StringAssert.StartsWith(_expectedBellatrixTitle, "Bellatrix" ); StringAssert.Matches("(281)388-0388" , @"(?d{3})?-? *d{3}-? *-?d{4}" ); StringAssert.DoesNotMatch("281)388-0388" , @"(?d{3})?-? *d{3}-? *-?d{4}" ); CollectionAssert.AreEqual(_expectedRockets, _actualRockets); CollectionAssert.AreNotEqual(_expectedRockets, _actualRockets); CollectionAssert.AreEquivalent(_expectedRockets, _actualRockets); CollectionAssert.AreNotEquivalent(_expectedRockets, _actualRockets); CollectionAssert.AllItemsAreInstancesOfType(_expectedRockets, _actualRockets); CollectionAssert.AllItemsAreNotNull(_expectedRockets); CollectionAssert.AllItemsAreUnique(_expectedRockets); CollectionAssert.Contains(_actualRockets, falcon9); CollectionAssert.DoesNotContain(_actualRockets, falcon9); CollectionAssert.IsSubsetOf(_expectedRockets, _actualRockets); CollectionAssert.IsNotSubsetOf(_expectedRockets, _actualRockets); Assert.ThrowsException<ArgumentNullException>(() => new Regex(null ));
指定輸入值 MSTest 可以使用在 [DataRow] 來對 [TestMethod] 加上多筆測試用的輸入資料,裡如下面的用法:
1 2 3 4 5 6 7 8 9 10 11 12 [TestMethod ] [DataRow(08, 07) ] [DataRow(12, 11) ] [DataRow(00, 23) ] public void 執行GetLastHourPeriod會取得上一個小時的區間(int hour, int expectedHour){ var date = new DateTime(2020 , 01 , 01 , hour, 00 , 00 ); var result = TimeHelper.GetLastHourPeriod(date); Assert.AreEqual(result.StartTime.Hour, expectedHour); Assert.AreEqual(result.EndTime.Hour, hour); }
並行執行單元測試 可以在單元測試的專案資料夾中加入 .runsettings 設定檔,並填寫以下設定:
1 2 3 4 5 6 7 8 <RunSettings > <MSTest > <Parallelize > <Workers > 4</Workers > <Scope > MethodLevel</Scope > </Parallelize > </MSTest > </RunSettings >
Workers 設定執行測試的並行處理數量。若要設定成連續的序列執行,設定成 0 即可。
Scope 指執行的程序是使用 Method Level 或 Class Level。若設定為 Method Level 則所有測試方法都會並行執行,若設定成 Class Level 則類別中的測試方法將採序列執行。如果測試方法之間有相依性,則必須採用 Class Level 的方式來處理。
.NET 單元測試 我會盡可能使用 MSTest 的方式來寫單元測試,只使用 MSTest 的內建功能,不使用第三方套件。
IOption 在 .NET 的架構下(非 .NET Framework),你會看到大量使用 Options 模式來處理設定值,如果你的專案中也有使用此模式,可以參考下面的方式來將設定注入至測試方法中。
使用 Microsoft.Extensions.Options 這個命名空間中的 Options.Create() 靜態方法,讓你可以產生出適合的注入設定物件。
.Net Unit Testing - Mock IOptionshttps://stackoverflow.com/questions/40876507/net-core-unit-testing-mock-ioptionst
https://stackoverflow.com/questions/41399526/how-to-initialize-ioptionappsettings-for-unit-testing-a-net-core-mvc-service/41399622
1 2 3 4 5 6 7 8 9 using using Microsoft.Extensions.Options;var appSettings = new AppSettings { Setting1 = "..." , Setting2 = "..." , }; var options = Options.Create(appSettings);var controller = new MyController(options);
ILogger、IMemoryCache、IHttpClient 使用 ServiceCollection 來建立 ServiceProvider,並透過 GetService 取得需要的物件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Caching.Memory;using Microsoft.Extensions.Logging.Abstractions;[TestClass ] public class SampleUnitTest { private ILoggerFactory loggerFactory; private IMemoryCache memoryCache; private IHttpClientFactory httpClientFactory; [TestInitialize ] public void Initialize () { var services = new ServiceCollection(); services.AddSingleton<ILoggerFactory, NullLoggerFactory>(); services.AddMemoryCache(); services.AddHttpClient(); var serviceProvider = services.BuildServiceProvider(); loggerFactory = _serviceProvider.GetService<ILoggerFactory>(); memoryCache = serviceProvider.GetService<IMemoryCache>(); memoryCachhttpClientFactory = serviceProvider.GetService<IHttpClientFactory>(); } [TestMethod ] public void SampleTest () { var logger = loggerFactory.CreateLogger<MyController>(); var controller = new MyController(logger, memoryCache); controller.TestSomething(); } }
參考資料: