文章目錄
Unit Test 想驗證 private static method 該怎麼做? - 使用 PrivateType
TDD 的第一天課程中就提到,以單元測試的角度 private method 不需單獨進行測試,在驗證 public 及 internal method 的過程中自然會涵蓋到 private or protected method,至於 static method 也是相同概念,只要有用到就需要測試
雖然知道透過 public or internal method 呼叫應該可以 cover 到 private static method,但有沒有粒度更小的測試空間呢?
基本環境
程式碼
public class ValuesController : ApiController { private static ILogger logger = LogManager.GetLogger("ValuesController"); public IHttpActionResult Post([FromBody] string value) { logger.Debug($"EventTime:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")};Value={value}"); var msg = GetNowReturn(value); if (string.IsNullOrEmpty(value)) return BadRequest(msg); else return Ok(msg); } } private static string GetNowReturn(string value) { return $"{DateTime.Today}-{value}"; }
如何測試?
最簡單的改法應該就是將
GetNowReturn
改為 internal
修改 private static 為 internal
internal string GetNowReturn(string value) { return $"{DateTime.Today}-{value}"; }
修改測試目標程式的 AssemblyInfo.cs 讓測試專案可以看見 internal method
- 開啟
Properties
下的AssemblyInfo.cs
- 加上
[assembly: InternalsVisibleTo("{測試專案名稱}")]
- 開啟
測試程式就可以直接呼叫改為
internal
的方法來驗證結果[TestMethod] public void GetNowReturn_Yowko_Return_DateTimeToday_value() { //arrange var target = new ValuesController(); string value = "Yowko"; var expected = $"{DateTime.Today}-{value}"; //act var actual = target.GetNowReturn(value); //assert Assert.AreEqual(expected, actual); }
有其他解決方式嗎? - 使用 PrivateType
在 Unit Test 該拿 static 屬性及欄位怎麼辦? - 使用 PrivateType 過程中看官方 api 說明時看到可以直接執行 static method
- 使用 PrivateType 來執行 private static method
不用修改 測試目標程式
public class ValuesController : ApiController { private static ILogger logger = LogManager.GetLogger("ValuesController"); public IHttpActionResult Post([FromBody] string value) { logger.Debug($"EventTime:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} Value={value}"); var msg = GetNowReturn(value); if (string.IsNullOrEmpty(value)) return BadRequest(msg); else return Ok(msg); } } private static string GetNowReturn(string value) { return $"{DateTime.Today}-{value}"; }
建立測試目標程式的 PrivateType 物件
PrivateType target = new PrivateType(typeof(ValuesController));
執行測試目標程式的 private static method
var actual = target.InvokeStatic("GetNowReturn", value);
最後程式碼
[TestMethod] public void GetNowReturn_Yowko_Return_DateTimeToday_value() { //arrange PrivateType target = new PrivateType(typeof(ValuesController)); string value = "Yowko"; var expected = $"{DateTime.Today}-{value}"; //act var actual = target.InvokeStatic("GetNowReturn", value); //assert Assert.AreEqual(expected, actual); }
心得
使用 PrivateType 來進行 static method 測試,就可以不用動到測試目標程式,相對風險更低,實際測試下來只要是 static 的 method 不論是 private、protected、internal、public 都可以使用 PrivateType 來進行測試,非常方便。
至於該不該單獨為 private method 測試,這就留給大家自行衡量,這邊就介紹 PrivateType 給大家認識,PrivateType 相關 api 可以參考 PrivateType Class
參考資訊
文章作者 Yowko Tsai
上次更新 2021-10-14
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。