在生產環境中測試,無水印。
在任何需要的地方都能運行。
獲得 30 天的全功能產品。
在幾分鐘內上手運行。
試用產品期間完全訪問我們的支援工程團隊
在軟體開發的世界中,測試是一個不可或缺的過程。 它確保您的程式碼按預期運行,並在錯誤到達生產環境之前幫助捕捉它們。 測試的一個重要方面是模擬,對於 C# 測試而言,MOQ 是開發人員工具庫中的一個強大工具。 它支持 lambda 表達式。 MOQ,意指“.NET的模擬物件框架”,簡化了為單元測試創建模擬物件的過程。 在本文中,我們將深入探討 C# 中的 MOQ。
MOQ - .NET 模擬框架 是一個用於 .NET 應用程式的模擬框架,允許開發人員快速有效地創建模擬對象。 模擬物件模擬您應用程式中實際物件的行為,使您更容易隔離和測試程式碼的特定部分。 MOQ 簡化了創建和使用這些模擬對象的過程。
在本教程中,我們將探討如何使用MOQ,一個流行的C#模擬框架,來促進單元測試。 我們將透過一個範例來演示如何使用 MOQ 模擬依賴關係,創建並測試一個簡單的 ATM 交易場景。
按照以下步驟創建新項目
打開Visual Studio,選擇 "檔案" > "新增" > "專案..."
選擇專案範本,配置設定,然後點選「建立」。
假設您正在為自動櫃員機開發軟體,並且需要測試驗證和取款功能。 ATM 依賴兩個介面:IHostBank
和 IHSMModule
。 我們想要測試ATMCashWithdrawal
類別,這個類別代表ATM的現金提取功能。
創建兩個介面,IHostBank
和 IHSMModule
,它們代表ATM系統的依賴項。 定義相關方法,例如authenticateAmount
和validatePIN
。
// 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
建立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
現在,讓我們使用 MOQ 模擬相依性,為ATMCashWithdrawal
類別創建單元測試。
在您的解決方案中創建一個新的單元測試專案,並將其命名為ATMSystem.Tests
。
要將 NUnit 測試專案添加到您的 Visual Studio 解決方案中,請按照以下步驟操作:
在方案上右鍵點擊:在方案總管(通常在右側),右鍵點擊方案名稱。
新增 > 新專案:從內容選單中選擇「新增」,然後選擇「新專案...」
建立新專案:在 "新增專案" 對話框中,您可以搜尋 "NUnit" 來找到可用的 NUnit 範本。 選擇如下所示的 NUnit 測試專案。
配置專案:根據需要配置專案設定,包括專案名稱和位置。
點擊確定:點擊“創建”或“確定”按鈕將 NUnit 測試項目添加到您的解決方案。
現在,你在解決方案中有一個單獨的 NUnit 測試專案,可以在其中編寫和管理單元測試。 您還可以添加引用至您想要測試的專案,並在此專案中開始撰寫您的 NUnit 測試案例。
若要開始在測試專案中使用 MOQ,您需要將 MOQ NuGet 套件新增至您的解決方案。 您可以使用 Visual Studio 中的 NuGet 套件管理器完成此操作,或在套件管理器控制台中運行以下命令:
Install-package moq
此命令將安裝該套件,並將所有必需的依賴項添加到項目中。
使用 NUnit 和 MOQ 撰寫單元測試,以模擬 ATMCashWithdrawal
類別的依賴項 (IHostBank
和 IHSMModule
)。
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
在此測試代碼中,我們使用 MOQ 來為 IHSMModule
和 IHostBank
創建模擬對象,並在測試期間調用時指定它們的行為。
在上述代碼範例中,我們演示了使用MOQ在C#中模擬對象的概念。 我們為 IHSMModule
和 IHostBank
介面創建模擬對象,模擬它們在單元測試期間的行為。 這使我們能夠通過控制這些模擬對象的響應來隔離並徹底測試ATMCashWithdrawal
類別。 通過模擬,我們可以確保我們的程式碼與這些依賴正確互動,使我們的測試更專注、可預測,並有效識別受檢單元程式碼中的問題。 這種做法提高了代碼的整體可靠性、可維護性,使測試代碼更容易。
構建您的解決方案以確保所有內容都是最新的。
在 Visual Studio 中打開測試總管(測試 > 測試總管)。
在測試總管中點選「全部執行」按鈕來執行您的單元測試。
檢查測試結果。 您應該看到您撰寫的測試(WithdrawAmount\_ValidTransaction\_ReturnsTrue
)通過。
![Moq C#(對開發者的運作方式)圖 3 - 要執行測試,首先必須建置解決方案。 成功建置後,請在 Visual Studio 中開啟 "Test Explorer",然後點擊 "Run All" 按鈕來開始您的單元測試執行。
這樣,我們可以隔離我們想要測試的代碼,並通過有效地模擬依賴項來確保它在各種場景下按預期行為。 這種做法提高了軟體的可靠性和可維護性,使得在開發過程的早期更容易識別和修復問題。
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
例如,如果您有一個涉及 PDF 生成或處理的專案,可以使用 IronPDF 創建模擬真實場景的 PDF 文件。 這對於測試和驗證您的程式碼如何與 PDF 檔案互動特別有用。 您可以生成具有特定內容、佈局和屬性的模擬 PDF,然後將它們用作測試固定裝置,以確保您的代碼產生所需的 PDF 輸出或正確處理與 PDF 相關的操作。
假設您正在開發一個生成財務報告的應用程式,並且這些報告需要以 PDF 文件的形式保存和分發。 在這種情況下,您可能需要測試 PDF 生成並確保內容和格式正確。
首先,我們需要將 IronPDF 添加到我們的專案中。 在 NuGet 套件管理器控制台中輸入以下命令來安裝 IronPDF。
Install-Package IronPdf
此命令將安裝並添加必要的相依項目到我們的專案中。
以下是如何將IronPDF整合到單元測試過程中的方法:
您可以使用 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
我們將編寫測試,使用 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
在此測試代碼中,我們生成一個模擬 PDF(expectedPdf
)來表示預期輸出,並將其與由 PDFGenerator
生成的 PDF(actualPDF
)進行比較。 我們已經提取了兩個 PDF 的內容來確認它們是否有相同的內容。
總結來說,在單元測試過程中結合使用MOQ與IronPDF,使我們能夠全面驗證軟體應用的行為。 MOQ 讓我們能夠隔離特定的代碼元件、控制依賴性,並模擬複雜的情境,使我們能夠撰寫專注且可靠的測試。
同時,IronPDF 透過促進 PDF 文件生成和操作,增強了我們的測試能力,確保我們的 PDF 相關功能得到徹底檢查。 通過將這些工具整合到我們的測試工具包中,我們可以自信地開發出既滿足功能又滿足性能要求的穩健和高品質軟體。 這種使用MOQ進行穩健的單元測試與使用IronPDF進行PDF驗證的結合,大大提高了我們應用程序的整體質量和可靠性。
值得注意的是,IronPDF 提供免費試用以測試其功能。 如果您認為它適合您的需求,您可以選擇購買商業授權,這可以讓您在專案中繼續使用IronPDF的功能,並享有隨附授權版本的全部優勢和支持,確保PDF相關功能順利整合到您的應用程式中。