在C#中進行單元測試

妙妙屋(zy)發表於2024-06-27

單元測試

前言

時隔多個月,終於抽空學習了點新知識,那麼這次來記錄一下C#怎麼進行單元測試,單元測試是做什麼的。

我相信大部分剛畢業的都很疑惑單元測試是幹什麼的?在小廠實習了6個月後,我發現每天除了寫CRUD就是寫CRUD,幾乎用不到單元測試。寫完一個功能直接上手去測,當然這只是我個人感受,僅供參考。

然後當我還在抱怨測試好煩的時候,大佬跟我說為什麼不用單元測試和整合測試,我這也是有苦說不出。要知道光學會理論知識,沒有實踐作為基礎,都是扯淡,入職這麼久還真沒用過單元測試,嚇得我趕緊去找資料學習。

那麼也是透過觀看B站某位Up主的影片,然後有點想法寫下這篇文章,雖然up主的主題是探究介面的作用和意義,但是影片中也講解了怎麼進行單元測試,所以對於介面理解不夠的可以去本文底部觀看影片學習。

那麼本篇文章就簡單的講解下C#中如何做單元測試,博主也是處於學習階段,有不對的地方歡迎指出改正。

單元測試簡述

單元測試(Unit Testing)是軟體開發中的一種測試方法,用於驗證程式碼中的最小可測試單元(通常是方法或函式)是否按照預期進行工作。這些單元通常是獨立於其他程式碼部分進行測試的,以確保其正確性和可靠性。

單元測試的主要作用:

  • 確保每個單元能正確執行預期功能
  • 能夠儘快找到Bug的具體位置

開始測試

本文以當前時間去返回早上好、中午好、晚上好來講解單元測試。

透過傳入不同的時間(邊界值)來確保程式碼能夠正確處理各種情況以及是否達到了預期的功能。

預期結果為:

  • 早上好...
  • 中午好...
  • 晚上好..

專案搭建

主程式

首先需要建立一個控制檯專案,起名為UnitTesting

並安裝Microsoft.Extensions.DependencyInjection包,管理IOC容器。

建立ITimeProvider介面,並建立SystemTimeProvider類去實現這個介面

public interface ITimeProvider
{
    int GetHour();
}
//返回當前時間
public class SystemTimeProvider: ITimeProvider
{
    public int GetHour()
    {
        return DateTime.Now.Hour;
    }
}

建立GreetingService

public class GreetingService
{
    private readonly ITimeProvider _timeProvider;

    public GreetingService(ITimeProvider timeProvider)
    {
        _timeProvider = timeProvider;
    }
    /// <summary>
    /// 透過當前時間來打返回問候語
    /// </summary>
    /// <param name="name"></param>
    /// <returns></returns>
    public string Greet(string name)
    {
        var hour = _timeProvider.GetHour();
        return hour switch
        {
            < 12 => $"Good Morning,{name}",
            < 18 => $"Good Afternoon,{name}",
            _ => $"Good Evening,{name}"
        };
    }
}

Program.cs使用IOC容器注入服務並呼叫Greet方法

using Microsoft.Extensions.DependencyInjection;
using UnitTesting.Services;

var container = new ServiceCollection();
container.AddSingleton<ITimeProvider,SystemTimeProvider>();
container.AddTransient<GreetingService>();
var services = container.BuildServiceProvider();

var greetingService = services.GetRequiredService<GreetingService>();
var greeting = greetingService.Greet("嗎嘍");
Console.WriteLine(greeting);

測試程式

xUnit模版建立單元測試,名為UnitTesting.Test,並新增UnitTesting專案引用,還需安裝Moq包:

Moq包(全稱Mocking Objects in C#,簡稱Moq)是一個流行的模擬框架,其主要作用在於模擬和驗證物件的行為,以支援更加可靠和可重複的測試,簡單來講就是模擬建立物件。

回到GreetingService類,這裡使用Rider提供的快捷方式建立測試類,當然也可以手動建立。如圖:

image

測試流程:

  • Arrange:準備階段,建立ITimeProvider的模擬物件provider,並指定時間引數且呼叫GetHour()方法,使用這個模擬物件建立GreetingService例項。
  • Act:執行階段,呼叫GreetingServiceGreet方法
  • Assert:斷言階段,驗證返回的訊息是否與預期的結果相同。
using JetBrains.Annotations;
using Moq;
using UnitTesting.Services;

namespace UnitTesting.Tes.Services;

[TestSubject(typeof(GreetingService))]
public class GreetingServiceTests
{
    [Fact]
    public void GreetReturnsMorningMessage()
    {
        // Arrange
        var provider = new Mock<ITimeProvider>();
        provider.Setup(x => x.GetHour()).Returns(10);
        var service = new GreetingService(provider.Object);

        // Act
        var message = service.Greet("嗎嘍");

        // Assert
        Assert.Equal("Good Morning,嗎嘍", message);
    }
    [Fact]
    public void GreetReturnsAfternoonMessage()
    {
        // Arrange
        var provider = new Mock<ITimeProvider>();
        provider.Setup(x => x.GetHour()).Returns(15);
        var service = new GreetingService(provider.Object);

        // Act
        var message = service.Greet("嗎嘍");

        // Assert
        Assert.Equal("Good Afternoon,嗎嘍", message);
    }
    [Fact]
    public void GreetReturnsEveningMessage()
    {
        // Arrange
        var provider = new Mock<ITimeProvider>();
        provider.Setup(x => x.GetHour()).Returns(20);
        var service = new GreetingService(provider.Object);

        // Act
        var message = service.Greet("嗎嘍");

        // Assert
        Assert.Equal("Good Evening,嗎嘍", message);
    }
}

效果截圖

主程式沒什麼好講的,透過當前時間返回問候語。

image

測試程式透過3個測試方法測試了3種情況,早上好、中午好、晚上好,並全部測試透過。

image

總結

本文講解了如何建立單元測試,並且透過單元測試來測試Greet方法,在傳入不同的時間引數的情況下,判斷是否滿足3種情況。

本文提到了IOC容器、依賴注入、Moq、xUnit等知識點。

參考連結

  • 【從單元測試出發探討介面的作用及意義】 https://www.bilibili.com/video/BV1Ut421V7Sz/?share_source=copy_web&vd_source=fce337a51d11a67781404c67ec0b5084
  • Asp-Net-Core學習筆記:單元測試和整合測試 - 程式設計實驗室 - 部落格園 (cnblogs.com) https://www.cnblogs.com/deali/p/17559685.html

相關文章