[Testing] NSubstitute 功能實作簡介

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/


希望此篇文章可以幫助到需要的人

若內容有誤或有其他建議請不吝留言給筆者喔 !