本文
比對兩個物件方式
首先我們建立一個測試用 Model。
public class TestModel
{
public string UserName { get; set; }
public string Account { get; set; }
}
建立一個測試方法驗證兩個物件是否相同。
[TestMethod()]
[Owner("Sian")]
[TestCategory("Class1")]
[TestProperty("Class1", "Object")]
public void ObjectTest_比較兩個相同物件_應回傳正確結果()
{
//arrange
var fistObject = new TestModel
{
Account = "abc",
UserName = "Sian"
};
var secondObject = new TestModel
{
Account = "abc",
UserName = "Sian"
};
secondObject.Should().Be(fistObject);
}
結果
有點奇怪,我們換回內建的方法測試看看。
[TestMethod()]
[Owner("Sian")]
[TestCategory("Class1")]
[TestProperty("Class1", "Object")]
public void ObjectTest_比較兩個相同物件_應回傳正確結果()
{
//arrange
var fistObject = new TestModel
{
Account = "abc",
UserName = "Sian"
};
var secondObject = new TestModel
{
Account = "abc",
UserName = "Sian"
};
//secondObject.Should().Be(fistObject);
//Assert.AreEqual(fistObject,secondObject);
Assert.AreSame(fistObject, secondObject);
}
還是一樣錯誤。
方法 | 定義 |
---|---|
AreSame() | 比較兩個物件的記憶體位址是否一致。 |
AreEqual() | AreEqual 則是繼承了原本 Object 使用的 Equals,也是比較記憶體位址。 |
所以如果要解決此種情況,就只能複寫原本的 AreEqual() 方法,所以基於懶惰原則,當然是另尋出路。
Fluentassertion 有提供這個方法比較,我們來測試看看。
[TestMethod()]
[Owner("Sian")]
[TestCategory("Class1")]
[TestProperty("Class1", "Object")]
public void ObjectTest_比較兩個相同物件_應回傳正確結果()
{
//arrange
var fistObject = new TestModel
{
Account = "abc",
UserName = "Sian"
};
var secondObject = new TestModel
{
Account = "abc",
UserName = "Sian"
};
//secondObject.Should().Be(fistObject);
//Assert.AreEqual(fistObject,secondObject);
//Assert.AreSame(fistObject, secondObject);
secondObject.Should().BeEquivalentTo(fistObject);
}
結果
比對兩個集合方式
一樣也可以透過 BeEquivalentTo 這個方法驗證。
[TestMethod()]
[Owner("Sian")]
[TestCategory("Class1")]
[TestProperty("Class1", "CollectionTest")]
public void CollectionTest_比較兩個集合_應回傳正確結果()
{
//arrange
var fistCollection = new List<TestModel>
{
new TestModel
{
Account = "abc",
UserName = "Sian"
}
};
var secondCollection = new List<TestModel>
{
new TestModel
{
Account = "abc",
UserName = "Sian"
}
};
secondCollection.Should().BeEquivalentTo(fistCollection);
}
結果
時間測試方法
首先我們建立一個會用到時間的方法。
public string GetNewYear()
{
if (DateTime.Now.Month == 1 &&
DateTime.Now.Day == 1)
{
return "Happy NEW YEAR!";
}
return "Today is not Holiday";
}
測試方法
[TestMethod()]
[Owner("Sian")]
[TestCategory("Class1")]
[TestProperty("Class1", "GetNewYear")]
public void GetNewYear_若今天不是新年_應回傳提示訊息()
{
//arrange
var target = new Class1();
var expected = "Today is not Holiday";
//act
var actual = target.GetNewYear();
//assert
actual.Should().Be(expected);
}
結果
現在我們遇到了一個問題,因為時間的關係,我們並不能測試如果是1/1的話是否會正確顯示提示訊息。
這時候我們可以自己撰寫一個擴充方法。
public static class SystemTime
{
internal static Func<DateTime> SetCurrentTime = () => DateTime.Now;
internal static Func<DateTime> SetToday = () => DateTime.Today;
public static DateTime Now => SetCurrentTime();
public static DateTime Today => SetToday();
}
接下來把 DateTime 改成使用 SystemTime。
public string GetNewYear()
{
if (SystemTime.Today.Month == 1 &&
SystemTime.Today.Day == 1)
{
return "Happy NEW YEAR!";
}
return "Today is not Holiday";
}
接下來為了讓測試專案可以改變 Internal 屬性,需要到 AssemblyInfo.cs 加入東西。
先切換成資料夾檢視。
為了要看到 AssemblyInfo.cs 需要先把顯示所有檔案打開。
搜尋 AssemblyInfo。
有 Debug 版本以及 Release 版本,兩個都要記得修改。
加入以下程式碼。
[assembly: InternalsVisibleTo("UnitTestProject")]
接著修改儲存完回到我們的測試。
[TestMethod()]
[Owner("Sian")]
[TestCategory("Class1")]
[TestProperty("Class1", "GetNewYear")]
public void GetNewYear_若今天是新年_應回傳提示訊息()
{
//arrange
var target = new Class1();
var expected = "Happy NEW YEAR!";
SystemTime.SetToday = () => new DateTime(year:2021,month:1,day:1);
//act
var actual = target.GetNewYear();
//assert
actual.Should().Be(expected);
}
結果: