在實際環境中測試
在生產環境中測試無浮水印。
在任何需要的地方都能運作。
在軟體開發的世界中,測試是一個不可或缺的過程。 它確保您的程式碼按預期運行,並在錯誤到達生產環境之前幫助捕捉它們。 測試的一個重要方面是模擬,對於 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 撰寫單元測試以模擬依賴項(IHostBank
和IHSMModule
)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
在此測試代碼中,我們使用 MOQ 來為 IHSMModule
和 IHostBank
創建模擬對象,並在測試期間指定它們被調用時的行為。
在上述代碼範例中,我們演示了使用MOQ在C#中模擬對象的概念。 我們為 IHSMModule
和 IHostBank
接口創建模擬對象,在單元測試期間模擬它們的行為。 這允許我們通過控制這些模擬物件的響應來隔離和徹底測試 ATMCashWithdrawal
類別。 通過模擬,我們可以確保我們的程式碼與這些依賴正確互動,使我們的測試更專注、可預測,並有效識別受檢單元程式碼中的問題。 這種做法提高了代碼的整體可靠性、可維護性,使測試代碼更容易。
構建您的解決方案以確保所有內容都是最新的。
在 Visual Studio 中打開測試探險家(測試 > 測試總管).
在測試總管中點選「全部執行」按鈕來執行您的單元測試。
檢查測試結果。 您應該看到您編寫的測試(WithdrawAmount_ValidTransaction_ReturnsTrue
)通過。
這樣,我們可以隔離我們想要測試的代碼,並通過有效地模擬依賴項來確保它在各種場景下按預期行為。 這種做法提高了軟體的可靠性和可維護性,使得在開發過程的早期更容易識別和修復問題。
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(預期的PDF
)表示預期輸出並將其與PDF進行比較(actualPDF
)由 PDFGenerator
生成。 我們已經提取了兩個 PDF 的內容來確認它們是否有相同的內容。
總之,利用 MOQ 並配合IronPDF 功能在我們的單元測試過程中,讓我們能夠全面驗證我們軟體應用程式的行為。 MOQ 讓我們能夠隔離特定的代碼元件、控制依賴性,並模擬複雜的情境,使我們能夠撰寫專注且可靠的測試。
同時,IronPDF 功能增強我們的測試能力,透過生成和操作 PDF 文件,確保我們的 PDF 相關功能得到徹底檢查。 通過將這些工具整合到我們的測試工具包中,我們可以自信地開發出既滿足功能又滿足性能要求的穩健和高品質軟體。 這種使用MOQ進行穩健的單元測試與使用IronPDF進行PDF驗證的結合,大大提高了我們應用程序的整體質量和可靠性。
值得注意的是,IronPDF 提供了一个IronPDF 免費試用測試其功能。 如果您覺得符合您的需求,您可以選擇購買一個IronPDF 商業授權使您能夠繼續在您的項目中使用IronPDF的功能,並充分享受授權版本所帶來的優勢和支持,確保PDF相關功能順利整合到您的應用程式中。