.NET 幫助

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

發佈 2023年10月29日
分享:

在軟件開發的世界中,測試是一個不可或缺的過程。它確保你的代碼按預期運行並幫助在進入生產環節之前抓住漏洞。測試的一個重要方面是模擬,而在進行 C# 測試時,MOQ 是開發人員武器庫中的一個強大工具。它提供了對 lambda 表達式的支持。MOQ,即“Mock Object Framework for .NET”的縮寫,簡化了為單元測試創建模擬對象的過程。在本文中,我們將深入探討 C# 中的 MOQ。

什麼是 MOQ?

最低訂購量 是一個針對 .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開發軟體 (自動櫃員機),並且您需要測試認證和提款功能。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. 在方案上右鍵點擊: 在方案總管中 (通常在右邊)1. 右鍵點擊解決方案名稱。

  2. 新增 > 新建專案: 從右鍵選單中,選擇“新增”然後選擇“新建專案...”

  3. 建立新專案: 在“新增新專案”對話框中,您可以搜索“NUnit”來查找可用的NUnit範本。選擇如下所示的NUnit測試專案。

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

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

  5. 點擊 OK: 點擊「建立」或「OK」按鈕,將 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 創建模擬對象,並在測試期間指定它們的行為。

在上面的代碼範例中,我們展示了在 C# 中使用 MOQ 進行對象模擬的概念。我們為 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的MOCK對象

假設你正在開發一個生成財務報告的應用程序,這些報告需要以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的功能,並享有授權版本所帶來的全部優勢和支援,確保PDF相關功能順利整合到您的應用程式中。

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

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

免費 NuGet 下載 總下載次數: 10,993,239 查看許可證 >