.NET 幫助

Moq C#(開發人員如何使用)

發佈 2023年10月29日
分享:

在軟體開發的世界中,測試是一個不可或缺的過程。 它確保您的程式碼按預期運行,並在錯誤到達生產環境之前幫助捕捉它們。 測試的一個重要方面是模擬,對於 C# 測試而言,MOQ 是開發人員工具庫中的一個強大工具。 它支持 lambda 表達式。 MOQ,意指“.NET的模擬物件框架”,簡化了為單元測試創建模擬物件的過程。 在本文中,我們將深入探討 C# 中的 MOQ。

什麼是 MOQ?

MOQ - .NET 的模擬框架是一個用於 .NET 應用程式的模擬框架,允許開發人員快速且高效地建立模擬物件。 模擬物件模擬您應用程式中實際物件的行為,使您更容易隔離和測試程式碼的特定部分。 MOQ 簡化了創建和使用這些模擬對象的過程。

MOQ 的主要功能

  • 流暢介面: MOQ 提供了一個流暢且富表達性的 API 用於設置期望和驗證。 這使您的測試程式碼更具可讀性且更易於理解。
  • 強類型化: MOQ 利用 C# 語言特性來提供強類型化和 IntelliSense 支援,當定義模擬和期望時。 這降低了測試中運行時錯誤的機率。
  • 寬鬆模擬: MOQ 支援嚴格和寬鬆模擬。 寬鬆的模擬允許您創建對任何方法調用都有回應的模擬對象,而嚴格模擬則強制只有預期的方法被調用。
  • 可驗證行為: MOQ 允許您驗證對模擬對象的特定方法是否以預期的參數和正確的順序被調用。
  • 回調和回傳值: 您可以定義回調,以在調用模擬方法時執行自訂程式碼,並為模擬的方法指定回傳值。

入門 MOQ

在本教程中,我們將探討如何使用MOQ,一個流行的C#模擬框架,來促進單元測試。 我們將透過一個範例來演示如何使用 MOQ 模擬依賴關係,創建並測試一個簡單的 ATM 交易場景。

建立新的 C

按照以下步驟創建新項目

  1. 開啟Visual Studio,請前往「檔案」>「新增」>「專案...」

  2. 選擇專案範本,配置設定,然後點選「建立」。

    Moq C#(開發人員的使用方式) 圖1 - 在Visual Studio 2022中創建一個新的控制台應用程式

    假設您正在為自動櫃員機開發軟體(自動櫃員機),您需要測試身份驗證和提款功能。 ATM 依賴於兩個介面:IHostBankIHSMModule。 我們想測試 ATMCashWithdrawal 類別,它代表 ATM 的取款功能。

    建立兩個介面,IHostBankIHSMModule,代表 ATM 系統的依賴項。 定義相關方法,例如 authenticateAmountvalidatePIN

// IHostBank.cs
public interface IHostBank
{
    bool AuthenticateAmount(string accountNumber, int amount);
}

// IHSMModule.cs
public interface IHSMModule
{
    bool ValidatePIN(string cardNumber, int pin);
}
// IHostBank.cs
public interface IHostBank
{
    bool AuthenticateAmount(string accountNumber, int amount);
}

// IHSMModule.cs
public interface IHSMModule
{
    bool ValidatePIN(string cardNumber, int pin);
}
' IHostBank.cs
Public Interface IHostBank
	Function AuthenticateAmount(ByVal accountNumber As String, ByVal amount As Integer) As Boolean
End Interface

' IHSMModule.cs
Public Interface IHSMModule
	Function ValidatePIN(ByVal cardNumber As String, ByVal pin As Integer) As Boolean
End Interface
VB   C#

創建 ATMCashWithdrawal 類別,使用上述的依賴來執行 ATM 操作。 在這堂課中,你將實作一個類似 WithdrawAmount 的方法。

// ATMCashWithdrawal.cs
public class ATMCashWithdrawal
{
    private readonly IHSMModule hsmModule;
    private readonly IHostBank hostBank;

    public ATMCashWithdrawal(IHSMModule hsmModule, IHostBank hostBank)
    {
        this.hsmModule = hsmModule;
        this.hostBank = hostBank;
    }
// non static method
    public bool WithdrawAmount(string cardNumber, int pin, int amount)
    {
        if (!hsmModule.ValidatePIN(cardNumber, pin))
        {
            return false;
        }

        if (!hostBank.AuthenticateAmount(cardNumber, amount))
        {
            return false;
        }

        // Withdraw the specified amount and perform other operations
        return true;
    }
}
// ATMCashWithdrawal.cs
public class ATMCashWithdrawal
{
    private readonly IHSMModule hsmModule;
    private readonly IHostBank hostBank;

    public ATMCashWithdrawal(IHSMModule hsmModule, IHostBank hostBank)
    {
        this.hsmModule = hsmModule;
        this.hostBank = hostBank;
    }
// non static method
    public bool WithdrawAmount(string cardNumber, int pin, int amount)
    {
        if (!hsmModule.ValidatePIN(cardNumber, pin))
        {
            return false;
        }

        if (!hostBank.AuthenticateAmount(cardNumber, amount))
        {
            return false;
        }

        // Withdraw the specified amount and perform other operations
        return true;
    }
}
' ATMCashWithdrawal.cs
Public Class ATMCashWithdrawal
	Private ReadOnly hsmModule As IHSMModule
	Private ReadOnly hostBank As IHostBank

	Public Sub New(ByVal hsmModule As IHSMModule, ByVal hostBank As IHostBank)
		Me.hsmModule = hsmModule
		Me.hostBank = hostBank
	End Sub
' non static method
	Public Function WithdrawAmount(ByVal cardNumber As String, ByVal pin As Integer, ByVal amount As Integer) As Boolean
		If Not hsmModule.ValidatePIN(cardNumber, pin) Then
			Return False
		End If

		If Not hostBank.AuthenticateAmount(cardNumber, amount) Then
			Return False
		End If

		' Withdraw the specified amount and perform other operations
		Return True
	End Function
End Class
VB   C#

建立單元測試專案

現在,讓我們使用MOQ模擬依賴項來為ATMCashWithdrawal類創建單元測試。

在您的解決方案中創建一個新的單元測試項目,並將其命名為 ATMSystem.Tests

要將 NUnit 測試專案添加到您的 Visual Studio 解決方案中,請按照以下步驟操作:

  1. 在解決方案上右鍵單擊: 在解決方案瀏覽器中(通常在右邊),右鍵單擊解決方案名稱。

  2. 新增 > 新增專案: 從內容選單中選擇「新增」,然後選擇「新增專案...」

  3. 建立新專案: 在「新增專案」對話框中,您可以搜尋「NUnit」以找到可用的 NUnit 範本。 選擇如下所示的 NUnit 測試專案。

    Moq C#(它是如何為開發者運作的)圖 2 - 在您的解決方案中添加一個新的 NUnit 測試專案。

  4. 配置專案: 根據需要配置專案設定,包括專案名稱和位置。

  5. 單擊“確定”: 單擊“創建”或“確定”按鈕將 NUnit 測試項目添加到您的解決方案。

    現在,你在解決方案中有一個單獨的 NUnit 測試專案,可以在其中編寫和管理單元測試。 您還可以添加引用至您想要測試的專案,並在此專案中開始撰寫您的 NUnit 測試案例。

    若要開始在測試專案中使用 MOQ,您需要將 MOQ NuGet 套件新增至您的解決方案。 您可以使用 Visual Studio 中的 NuGet 套件管理器完成此操作,或在套件管理器控制台中運行以下命令:

Install-package moq

此命令將安裝該套件,並將所有必需的依賴項添加到項目中。

使用 NUnit 和 MOQ 撰寫單元測試以模擬依賴項(IHostBankIHSMModule)ATMCashWithdrawal 類別的。

using Moq;
using MOQTestProject;

namespace UnitTest
{
    public class Tests
    {
        ATMCashWithdrawal atmCash;
        [SetUp]
        public void Setup()
        {
            // Arrange
            var hsmModuleMock = new Mock<IHSMModule>();
            hsmModuleMock.Setup(h => h.ValidatePIN("123456781234", 1234)).Returns(true);

            var hostBankMock = new Mock<IHostBank>();
            hostBankMock.Setup(h => h.AuthenticateAmount("123456781234", 500)).Returns(true);
            var atmCash = new ATMCashWithdrawal(hsmModuleMock.Object, hostBankMock.Object); // Object property
        }

        [Test]
        public void WithdrawAmount_ValidTransaction_ReturnsTrue()
        {
            // Act
            bool result = atmCash.WithdrawAmount("123456781234", 1234, 500);

            // Assert
            Assert.IsTrue(result); // Verify method 
        }

        // Add more test cases for different scenarios (e.g., invalid PIN, insufficient funds, etc.)
    }
}
using Moq;
using MOQTestProject;

namespace UnitTest
{
    public class Tests
    {
        ATMCashWithdrawal atmCash;
        [SetUp]
        public void Setup()
        {
            // Arrange
            var hsmModuleMock = new Mock<IHSMModule>();
            hsmModuleMock.Setup(h => h.ValidatePIN("123456781234", 1234)).Returns(true);

            var hostBankMock = new Mock<IHostBank>();
            hostBankMock.Setup(h => h.AuthenticateAmount("123456781234", 500)).Returns(true);
            var atmCash = new ATMCashWithdrawal(hsmModuleMock.Object, hostBankMock.Object); // Object property
        }

        [Test]
        public void WithdrawAmount_ValidTransaction_ReturnsTrue()
        {
            // Act
            bool result = atmCash.WithdrawAmount("123456781234", 1234, 500);

            // Assert
            Assert.IsTrue(result); // Verify method 
        }

        // Add more test cases for different scenarios (e.g., invalid PIN, insufficient funds, etc.)
    }
}
Imports Moq
Imports MOQTestProject

Namespace UnitTest
	Public Class Tests
		Private atmCash As ATMCashWithdrawal
		<SetUp>
		Public Sub Setup()
			' Arrange
			Dim hsmModuleMock = New Mock(Of IHSMModule)()
			hsmModuleMock.Setup(Function(h) h.ValidatePIN("123456781234", 1234)).Returns(True)

			Dim hostBankMock = New Mock(Of IHostBank)()
			hostBankMock.Setup(Function(h) h.AuthenticateAmount("123456781234", 500)).Returns(True)
			Dim atmCash = New ATMCashWithdrawal(hsmModuleMock.Object, hostBankMock.Object) ' Object property
		End Sub

		<Test>
		Public Sub WithdrawAmount_ValidTransaction_ReturnsTrue()
			' Act
			Dim result As Boolean = atmCash.WithdrawAmount("123456781234", 1234, 500)

			' Assert
			Assert.IsTrue(result) ' Verify method
		End Sub

		' Add more test cases for different scenarios (e.g., invalid PIN, insufficient funds, etc.)
	End Class
End Namespace
VB   C#

在此測試代碼中,我們使用 MOQ 來為 IHSMModuleIHostBank 創建模擬對象,並在測試期間指定它們被調用時的行為。

在上述代碼範例中,我們演示了使用MOQ在C#中模擬對象的概念。 我們為 IHSMModuleIHostBank 接口創建模擬對象,在單元測試期間模擬它們的行為。 這允許我們通過控制這些模擬物件的響應來隔離和徹底測試 ATMCashWithdrawal 類別。 通過模擬,我們可以確保我們的程式碼與這些依賴正確互動,使我們的測試更專注、可預測,並有效識別受檢單元程式碼中的問題。 這種做法提高了代碼的整體可靠性、可維護性,使測試代碼更容易。

步驟3 執行測試

  1. 構建您的解決方案以確保所有內容都是最新的。

  2. 在 Visual Studio 中打開測試探險家(測試 > 測試總管).

  3. 在測試總管中點選「全部執行」按鈕來執行您的單元測試。

  4. 檢查測試結果。 您應該看到您編寫的測試(WithdrawAmount_ValidTransaction_ReturnsTrue)通過。

    Moq C#(開發者如何使用)圖 3 - 要運行測試,首先必須構建解決方案。 成功建置後,打開 Visual Studio 中的“測試總管”,然後點擊“全部執行”按鈕以開始執行單元測試。

    這樣,我們可以隔離我們想要測試的代碼,並通過有效地模擬依賴項來確保它在各種場景下按預期行為。 這種做法提高了軟體的可靠性和可維護性,使得在開發過程的早期更容易識別和修復問題。

介紹 IronPDF

IronPDF 文件和功能概述是一個強大的 C# 函式庫,允許開發人員在其應用程式中處理 PDF 文件。 它提供了廣泛的功能,包括從各種來源(如 HTML、圖像和現有的 PDF)創建、修改和轉換 PDF 文件。 當結合使用前一教程中討論的模擬對象概念時,IronPDF 可成為在單元測試中生成和操作 PDF 文件的有價值工具。

IronPDF 的主要功能是其HTML 轉 PDF確保布局和樣式保持完整的功能。 它將網頁內容轉換為PDF,非常適合報告、發票和文件。 此功能支持將 HTML 檔案、URL 和 HTML 字串轉換為 PDF。

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
Imports IronPdf

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		Dim renderer = New ChromePdfRenderer()

		' 1. Convert HTML String to PDF
		Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
		Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
		pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")

		' 2. Convert HTML File to PDF
		Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
		Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
		pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")

		' 3. Convert URL to PDF
		Dim url = "http://ironpdf.com" ' Specify the URL
		Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
		pdfFromUrl.SaveAs("URLToPDF.pdf")
	End Sub
End Class
VB   C#

例如,如果您有一個涉及 PDF 生成或處理的專案,可以使用 IronPDF 創建模擬真實場景的 PDF 文件。 這對於測試和驗證您的程式碼如何與 PDF 檔案互動特別有用。 您可以生成具有特定內容、佈局和屬性的模擬 PDF,然後將它們用作測試固定裝置,以確保您的代碼產生所需的 PDF 輸出或正確處理與 PDF 相關的操作。

創建用於生成 PDF 的模擬物件

假設您正在開發一個生成財務報告的應用程式,並且這些報告需要以 PDF 文件的形式保存和分發。 在這種情況下,您可能需要測試 PDF 生成並確保內容和格式正確。

首先,我們需要將 IronPDF 添加到我們的專案中。 在 NuGet 套件管理器控制台中輸入以下命令來安裝 IronPDF。

Install-Package IronPdf

此命令將安裝並添加必要的相依項目到我們的專案中。

以下是如何將IronPDF整合到單元測試過程中的方法:

生成模擬PDF

您可以使用 IronPDF 建立帶有特定內容和樣式的模擬 PDF 文件,以模仿真實的財務報告。 以下範例代碼說明了這些模擬 PDF 如何用作單元測試的測試夾具:

public class PDFGenerator
{
    public void GenerateFinancialReport(string reportData)
    {
        var renderer = new ChromePdfRenderer();
        // Generate the report HTML
        string reportHtml = GenerateReportHtml(reportData);
        PdfDocument pdfDocument = renderer.RenderHtmlAsPdf(reportHtml);
        // Save the PDF to a file or memory stream
        pdfDocument.SaveAsPdfA("FinancialReport.pdf");
    }

    private string GenerateReportHtml(string reportData)
    {
        // Generate the report HTML based on the provided data
        // (e.g., using Razor views or any HTML templating mechanism)
        // Return the HTML as a string

        return "<h1>my Report</h1>";
    }
}
public class PDFGenerator
{
    public void GenerateFinancialReport(string reportData)
    {
        var renderer = new ChromePdfRenderer();
        // Generate the report HTML
        string reportHtml = GenerateReportHtml(reportData);
        PdfDocument pdfDocument = renderer.RenderHtmlAsPdf(reportHtml);
        // Save the PDF to a file or memory stream
        pdfDocument.SaveAsPdfA("FinancialReport.pdf");
    }

    private string GenerateReportHtml(string reportData)
    {
        // Generate the report HTML based on the provided data
        // (e.g., using Razor views or any HTML templating mechanism)
        // Return the HTML as a string

        return "<h1>my Report</h1>";
    }
}
Public Class PDFGenerator
	Public Sub GenerateFinancialReport(ByVal reportData As String)
		Dim renderer = New ChromePdfRenderer()
		' Generate the report HTML
		Dim reportHtml As String = GenerateReportHtml(reportData)
		Dim pdfDocument As PdfDocument = renderer.RenderHtmlAsPdf(reportHtml)
		' Save the PDF to a file or memory stream
		pdfDocument.SaveAsPdfA("FinancialReport.pdf")
	End Sub

	Private Function GenerateReportHtml(ByVal reportData As String) As String
		' Generate the report HTML based on the provided data
		' (e.g., using Razor views or any HTML templating mechanism)
		' Return the HTML as a string

		Return "<h1>my Report</h1>"
	End Function
End Class
VB   C#

使用模擬 PDF 進行單元測試

我們將編寫測試,使用 IronPDF 生成代表各種報告場景的模擬 PDF。 然後,我們將把我們代碼生成的實際PDF與這些模擬PDF進行比較,以確保內容、格式和結構如預期一致。

internal class PDFGeneratorTests
{
    [Test]
    public void GenerateFinancialReport_CreatesCorrectPDF()
    {
        // Arrange
        var mock = new PDFGenerator();
        var expectedPdf = PdfDocument.FromFile("ExpectedFinancialReport.pdf"); // Load a mock PDF

        // Act
        mock.GenerateFinancialReport("Sample report data");
        var actualPdf = PdfDocument.FromFile("FinancialReport.pdf");

        // Assert
        Assert.AreEqual(actualPdf.ExtractAllText() , expectedPdf.ExtractAllText());
    }

}
internal class PDFGeneratorTests
{
    [Test]
    public void GenerateFinancialReport_CreatesCorrectPDF()
    {
        // Arrange
        var mock = new PDFGenerator();
        var expectedPdf = PdfDocument.FromFile("ExpectedFinancialReport.pdf"); // Load a mock PDF

        // Act
        mock.GenerateFinancialReport("Sample report data");
        var actualPdf = PdfDocument.FromFile("FinancialReport.pdf");

        // Assert
        Assert.AreEqual(actualPdf.ExtractAllText() , expectedPdf.ExtractAllText());
    }

}
Friend Class PDFGeneratorTests
	<Test>
	Public Sub GenerateFinancialReport_CreatesCorrectPDF()
		' Arrange
		Dim mock = New PDFGenerator()
		Dim expectedPdf = PdfDocument.FromFile("ExpectedFinancialReport.pdf") ' Load a mock PDF

		' Act
		mock.GenerateFinancialReport("Sample report data")
		Dim actualPdf = PdfDocument.FromFile("FinancialReport.pdf")

		' Assert
		Assert.AreEqual(actualPdf.ExtractAllText(), expectedPdf.ExtractAllText())
	End Sub

End Class
VB   C#

在這個測試代碼中,我們生成一個模擬 PDF(預期的PDF)表示預期輸出並將其與PDF進行比較(actualPDF)由 PDFGenerator 生成。 我們已經提取了兩個 PDF 的內容來確認它們是否有相同的內容。

結論

總之,利用 MOQ 並配合IronPDF 功能在我們的單元測試過程中,讓我們能夠全面驗證我們軟體應用程式的行為。 MOQ 讓我們能夠隔離特定的代碼元件、控制依賴性,並模擬複雜的情境,使我們能夠撰寫專注且可靠的測試。

同時,IronPDF 功能增強我們的測試能力,透過生成和操作 PDF 文件,確保我們的 PDF 相關功能得到徹底檢查。 通過將這些工具整合到我們的測試工具包中,我們可以自信地開發出既滿足功能又滿足性能要求的穩健和高品質軟體。 這種使用MOQ進行穩健的單元測試與使用IronPDF進行PDF驗證的結合,大大提高了我們應用程序的整體質量和可靠性。

值得注意的是,IronPDF 提供了一个IronPDF 免費試用測試其功能。 如果您覺得符合您的需求,您可以選擇購買一個IronPDF 商業授權使您能夠繼續在您的項目中使用IronPDF的功能,並充分享受授權版本所帶來的優勢和支持,確保PDF相關功能順利整合到您的應用程式中。

< 上一頁
Entity Framework C#(開發人員的工作原理)
下一個 >
C# 網頁框架(開發人員如何使用)

準備開始了嗎? 版本: 2024.11 剛剛發布

免費 NuGet 下載 總下載次數: 11,493,407 查看許可證 >