在昨天 Day-10 把 EmailSystem 從 JJEmail 這隻套件抽離;同時,在測試方面也針對 EmailFunction 撰寫了一隻帶有虛設常式的測試,可以看到在最後測試的時候寫了一隻百分百會回傳 "Success" 的功能。
然而,這樣的測試實際上是沒有意義的;其原因在於
using NUnit3;
[TestFixture]
public class EmailSystemUnitTests
{
[Test]
public void EmailFunction_Success()
{
// Arrange
StubEmailSerivce stubEmailService = new StubEmailSerivce();
EmailSystem EmailService = new EmailSystem(stubEmailService);
// Act
var stubResult = EmailSystem.EmailFunction("Test@abc.com.tw", "Test Demo");
// Assert
Assert.AreEqual("Success", stubResult);
}
}
public class StubEmailSerivce : IEmailService
{
public string SendEmail(EmailAddress, EmailMessage)
{
return "Success";
}
}
那既然如此,為何還需要虛設常式呢?在這之前,我們先換種角度觀察,來看看商業邏輯的流程,也就是 EmailFunction。
在昨天 Day-10 中,我們有提到 EmailSystem 的 EmailFunction 目前的功能:
public class EmailSystem
{
...
public string EmailFunction(string EmailAddress, string EmailMessage)
{
var EmailFinalResult = EmailServiece.SendEmail(EmailAddress, EmailMessage);
return EmailFinalResult;
}
}
那假設今天變更需求,要在寄送 Email 之前確認 EmailMessage 是否帶有髒字(是否定義為髒字牽涉到語義學,為了不模糊主題,我們僅偵測是否帶有“傻瓜”字眼),若不符合條件則回傳失敗。因此,程式碼改寫如下:
public class EmailSystem
{
...
public string EmailFunction(string EmailAddress, string EmailMessage)
{
// 確認是否帶有髒字
var SendEmail = false;
if (!EmailMessage.Contains("傻瓜"))
{
SendEmail = true;
}
// 寄送 E-mail 方法
var EmailFinalResult = "Fail";
if (SendEmail == true)
{
var EmailFinalResult = EmailServiece.SendEmail(EmailAddress, EmailMessage);
}
return EmailFinalResult;
}
}
寫到這邊,是不是測試的項目也要隨之變動了,而不再是單純測試是否會回傳 “Success” 這個功能。而是要針對是否帶有“傻瓜”字眼判別寄信成果;因此,單元測試程式碼如下:
using NUnit3;
[TestFixture]
public class EmailSystemUnitTests
{
[Test]
public void EmailFunction_NotContainFool_Success()
{
// Arrange
StubEmailSerivce stubEmailService = new StubEmailSerivce();
EmailSystem EmailService = new EmailSystem(stubEmailService);
// Act
var Result = EmailSystem.EmailFunction("Test@abc.com.tw", "Test Demo");
// Assert
Assert.AreEqual("Success", Result);
}
[Test]
public void EmailFunction_ContainFool_Fail()
{
// Arrange
StubEmailSerivce stubEmailService = new StubEmailSerivce();
EmailSystem EmailService = new EmailSystem(stubEmailService);
// Act
var Result = EmailSystem.EmailFunction("Test@abc.com.tw", "傻瓜 呵呵");
// Assert
Assert.AreEqual("Fail", Result);
}
}
public class StubEmailSerivce : IEmailService
{
public string SendEmail(EmailAddress, EmailMessage)
{
return "Success";
}
}
所以,在這邊測試的目的就很明確了,就是要測試是否有正確判別 EmailMessage 是否能針對字串帶有 “傻瓜” 的字眼做出正確的判別。而 StubEmailSerivce 所做的事情就是要把 EmailServiece.SendEmail(EmailAddress, EmailMessage) 的影響排除掉。
以作者自己的觀點,微軟大多很熱門的套件大多不會有出錯的可能性,但今天是使用合作公司或來路不明的 .dll 檔案(舉例來說,在政府接專案可能是承接前一家廠商做到一半的東西,而交接東西不完全的情況)。此時,這個 .dll 黑盒子的可信度就有待評估。因此,透過虛設常式就可以過濾這種風險。
明天會開始介紹虛設常式的好兄弟——模擬物件 (Mock)。