NSubstitute 功能實作簡介
前言
最近接觸到眾多前輩推薦的 Mock Framework - NSubstitute,為了實行搞搞就懂的精神,因此以下將使用一個簡單實例,簡單紀錄一下NSubstitute提供的常見功能。
測試實例
主要就是一個告警管理者(AlertManager),會依注入的警示方式(notification)及對象(targets)來執行告警任務(Alert);在警示方式介面(INotification)中定義了一個警示功能(Notify)方法,並依緊急程度區分為兩個等級(Normal / Urgent),且有個運算(Calculate)功能方法於其中。以下參考。
public enum Level
{
Normal,
Urgent
}
public interface INotification
{
Level Level { get; set; }
void Notify(string target);
int Calculate(int value1, int value2);
}
public class AlertManager
{
// Fields
INotification _notification;
List<string> _targets;
// Constructors
public AlertManager(INotification notification, List<string> targets)
{
_notification = notification;
_targets = targets;
}
// Methods
public void Alert()
{
if (_targets == null)
{ throw new Exception("no targets"); }
foreach (var target in _targets)
{ _notification.Notify(target); }
}
}
功能簡介
NSubstitute提供了許多實用功能來協助我們執行單元測試,大多就是"控制"測試替身方法與屬性回傳值,以及"紀錄"測試替身方法被調用的情況,以下將就常使用的功能進行實作。以下參考。
回傳特定數值
1. 對應輸入特定參數
[TestMethod]
public void 回傳特定數值_輸入特定參數()
{
// Arrange
var notification = Substitute.For<INotification>();
// intput (1, 1) return "2"
notification.Calculate(1, 1).Returns(2);
notification.Calculate(1, 2).Returns(3);
// Act & Assert
Assert.AreEqual(notification.Calculate(1, 1), 2);
Assert.AreEqual(notification.Calculate(1, 2), 3);
}
2. 對應輸入任意參數
[TestMethod]
public void 回傳特定數值_輸入任意參數()
{
// Arrange
var notification = Substitute.For<INotification>();
// intput (any, any) return "2"
notification.Calculate(0, 0).ReturnsForAnyArgs(2);
// Act & Assert
Assert.AreEqual(notification.Calculate(1, 1), 2);
Assert.AreEqual(notification.Calculate(1, 2), 2);
}
3. 對應輸入條件參數
[TestMethod]
public void 回傳特定數值_輸入條件參數()
{
// Arrange
var notification = Substitute.For<INotification>();
// intput (any1, any2) return " 99", when any1 > 0
notification.Calculate(Arg.Is<int>(x => x > 0), Arg.Any<int>()).Returns(99);
notification.Calculate(Arg.Is<int>(x => x < 0), Arg.Any<int>()).Returns(-99);
// Act & Assert
Assert.AreEqual(notification.Calculate(1, 0), 99);
Assert.AreEqual(notification.Calculate(-1, 0), -99);
}
回傳函式化特定數值
[TestMethod]
public void 回傳函式化特定數值()
{
// Arrange
var notification = Substitute.For<INotification>();
// intput (any1, any2) return "2*(any1+any2)"
notification.Calculate(0, 0).ReturnsForAnyArgs(x =>
{
int arg1 = (int)x[0];
int arg2 = (int)x[1];
return 2 * (arg1 + arg2);
});
// Act & Assert
Assert.AreEqual(notification.Calculate(1, 1), 4);
Assert.AreEqual(notification.Calculate(1, 2), 6);
}
回傳清單式特定數值
[TestMethod]
public void 回傳清單式特定數值()
{
// Arrange
var notification = Substitute.For<INotification>();
// return "Addition", "Subtraction" in order
notification.Level.Returns(Level.Normal, Level.Urgent);
// Act & Assert
Assert.AreEqual(notification.Level, Level.Normal);
Assert.AreEqual(notification.Level, Level.Urgent);
}
檢查調用次數
[TestMethod]
public void 檢查調用次數()
{
// Arrange
var notification = Substitute.For<INotification>();
var targets = new List<string>() { "0958123123" };
var alertManager = new AlertManager(notification, targets);
// Act
alertManager.Alert();
alertManager.Alert();
// Assert
notification.ReceivedWithAnyArgs(2).Notify("");
}
檢查特定參數調用
[TestMethod]
public void 檢查特定參數調用()
{
// Arrange
var notification = Substitute.For<INotification>();
var targets = new List<string>() { "0958111111", "0958222222" };
var alertManager = new AlertManager(notification, targets);
// Act
alertManager.Alert();
// Assert
notification.Received().Notify("0958111111");
notification.Received().Notify("0958222222");
notification.Received().Notify(Arg.Is<string>(x => x.Contains("0958")));
}
檢查拋出異常
[TestMethod]
[ExpectedException(typeof(Exception))]
public void 檢查拋出異常()
{
// Arrange
var notification = Substitute.For<INotification>();
var alertManager = new AlertManager(notification, null);
// Act
alertManager.Alert();
}
參考資訊
http://nsubstitute.github.io/help/getting-started/
希望此篇文章可以幫助到需要的人
若內容有誤或有其他建議請不吝留言給筆者喔 !