.NET ヘルプ

開発者向けMoq C#(その仕組み)

公開済み 2023年10月29日
共有:

ソフトウェア開発の世界では、テストは欠かせないプロセスです。 それはコードが期待通りに動作することを保証し、バグが本番環境に到達する前に発見するのに役立ちます。 テストの重要な側面の一つはモックであり、C#のテストにおいて、MOQは開発者の強力なツールです。 ラムダ式のサポートを提供します。 MOQは、「.NET用のモックオブジェクトフレームワーク」の略で、単体テストのためのモックオブジェクトを作成するプロセスを簡素化します。 この記事では、C#のMOQについて掘り下げます。

MOQとは何ですか?

MOQ - .NET 用モッキングフレームワークは、開発者がモックオブジェクトを迅速かつ効率的に作成できる .NET アプリケーション用のモッキングフレームワークです。 モック・オブジェクトは、アプリケーション内の実際のオブジェクトの動作をシミュレートし、コードの特定部分の切り分けとテストを容易にします。 MOQは、これらのモックオブジェクトの作成および操作プロセスを簡素化します。

MOQの主な機能

  • 流暢なインターフェイス: MOQは期待値と検証を設定するための流暢で表現力豊かなAPIを提供します。 これにより、テストコードが読みやすく理解しやすくなります。
  • 強い型付け: MOQ は、モックおよび期待を定義する際に強い型付けと IntelliSense サポートを提供するために C# 言語機能を活用します。 これにより、テストにおける実行時エラーの可能性が減少します。
  • ルーズモッキング: MOQ は厳格なモッキングとルーズなモッキングの両方をサポートします。 ルーズモッキングでは、任意のメソッド呼び出しに応答するモックオブジェクトを作成できますが、厳格モッキングでは、予期されたメソッドのみが呼び出されることが求められます。
  • 検証可能な動作: MOQは、モックオブジェクトの特定のメソッドが期待される引数と正しい順序で呼び出されたことを検証することを可能にします。
  • コールバックとリターン: モックされたメソッドが呼び出されたときにカスタムコードを実行するためのコールバックを定義し、モックされたメソッドの戻り値を指定できます。

MOQの使い方はじめに

このチュートリアルでは、C#のユニットテストを容易にするために、人気のあるモックフレームワークであるMOQの使い方を探っていきます。 以下は、MOQを使用して依存関係をモックし、シンプルなATM取引シナリオを作成およびテストする例を説明します。

新しいC#を作成する

以下の手順に従って新しいプロジェクトを作成します

  1. 開くビジュアルスタジオ「ファイル」 > 「新規」 > 「プロジェクト...」に移動します

  2. プロジェクトテンプレートを選択し、設定を構成して、「作成」をクリックします。

    Moq C#(開発者向けの動作説明)図1 - Visual Studio 2022で新しいコンソールアプリケーションを作成する

    ATM向けのソフトウェアを開発しているとします(自動現金預け払い機)認証と引き出し機能をテストする必要があります。 ATMは、IHostBankおよびIHSMModuleの二つのインターフェースに依存しています。 私たちは、ATMのキャッシュ引き出し機能を表す ATMCashWithdrawal クラスをテストしたいと考えています。

    ATMシステムの依存関係を表す2つのインターフェース、IHostBankIHSMModuleを作成します。 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#

上記の依存関係を使用してATM操作を実行するATMCashWithdrawalクラスを作成します。 このクラスでは、「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#

ユニットテストプロジェクトを作成

さて、依存関係をMockitoでモックするためのATMCashWithdrawalクラスのユニットテストを作成しましょう。

ソリューションに新しい単体テストプロジェクトを作成し、ATMSystem.Testsとして名前を付けます。

Visual StudioソリューションにNUnitテストプロジェクトを追加するには、以下の手順に従ってください:

  1. ソリューションを右クリックします: ソリューションエクスプローラー内(通常、右側に)ソリューション名を右クリックします。

  2. 追加 > 新しいプロジェクト: コンテキストメニューから、「追加」を選択し、その後「新しいプロジェクト...」を選択します。

  3. 新しいプロジェクトの作成: 「新しいプロジェクトの追加」ダイアログで、「NUnit」を検索して利用可能なNUnitテンプレートを見つけることができます。 以下のように NUnit テスト プロジェクトを選択します。

    Moq C#(開発者向けの動作方法)図2 - ソリューションに新しいNUnitテストプロジェクトを追加します。

  4. プロジェクトの設定: プロジェクト名や場所など、必要に応じてプロジェクト設定を構成します。

  5. 「OK」をクリック: ソリューションにNUnitテストプロジェクトを追加するには、「Create」または「OK」ボタンをクリックしてください。

    さて、ソリューション内に独立した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
VB   C#

このテストコードでは、MOQを使用してIHSMModuleおよびIHostBankのモックオブジェクトを作成し、テスト中に呼び出されたときの挙動を指定しています。

上記のコード例では、C#でMOQを使用してオブジェクトをモックするコンセプトを示しました。 IHSMModuleインターフェースとIHostBankインターフェースのモックオブジェクトを作成し、単体テスト中にそれらの動作をシミュレートします。 これにより、これらのモックオブジェクトの応答を制御することで、ATMCashWithdrawalクラスを分離して徹底的にテストすることができます。 モックを使用することで、コードがこれらの依存関係と正しく相互作用していることを確認できるため、テストを集中させ予測可能で効果的に行うことができ、検査対象の特定のコードユニット内の問題を特定することができます。 このプラクティスは、コードの信頼性、保守性を向上させ、テストを容易にします。

ステップ3 テストの実行

  1. ソリューションを構築して、すべてが最新の状態になっていることを確認してください。

  2. Visual Studioでテストエクスプローラーを開きます(テスト > テスト エクスプローラー).

  3. 「テストエクスプローラー」で「すべて実行」ボタンをクリックして、ユニットテストを実行します。

  4. テスト結果を確認してください。 あなたが書いたテストを見るべきです。(WithdrawAmount_ValidTransaction_ReturnsTrue(WithdrawAmount_ValidTransaction_ReturnsTrue))パス。

    Moq C#(開発者向けの仕組み)図3 - テストを実行するには、まずソリューションをビルドする必要があります。 ビルドが成功した後、Visual Studioで「Test Explorer」を開き、「Run All」ボタンをクリックしてユニットテストの実行を開始します。

    このようにして、テストしたいコードを分離し、依存関係を効果的にモックすることにより、様々なシナリオで期待通りに動作することを確認することができます。 この実践は、ソフトウェアの信頼性と保守性を向上させ、開発プロセスの早い段階で問題を特定し修正することを容易にします。

IronPDFの紹介

IronPDF ドキュメントと機能の概要は、開発者がアプリケーション内でPDFドキュメントを扱うことができる強力なC#ライブラリです。 さまざまな機能を提供し、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をプロジェクトに追加する必要があります。 IronPDFをインストールするためにNuGetパッケージマネージャーコンソールで次のコマンドを書いてください。

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を使用した単体テスト

私たちは、様々なレポートシナリオを表すモックPDFを生成するためにIronPDFを使用するテストを書きます。 次に、コードで生成された実際の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を生成します。(expectedPdf)期待される出力を表現し、それをPDFと比較します(実際のPDF)PDFGeneratorによって生成された。 両方のPDFの内容を抽出して、同じ内容であるかどうかを確認しました。

結論

結論として、MOQを利用することは、IronPDFの機能私たちの単体テストプロセスでは、ソフトウェアアプリケーションの動作を包括的に検証することができます。 MOQは、特定のコードコンポーネントを分離し、依存関係を制御し、複雑なシナリオをシミュレートすることを可能にし、焦点を絞った信頼性の高いテストを作成できるようにします。

その間IronPDFの機能PDFドキュメントの生成と操作を容易にすることで、テスト機能を強化し、PDF関連の機能を徹底的に検証できるようにします。 これらのツールをテストツールキットに統合することにより、機能性とパフォーマンスの両方の要求を満たす堅牢で高品質なソフトウェアを自信を持って開発することができます。 これほど強力な単体テストと MOQ と IronPDF を使用した PDF 検証の組み合わせは、アプリケーション全体の品質と信頼性に大きく貢献しています。

IronPDFは提供していることを特筆すべきですIronPDFの無料トライアルその機能をテストするために。 もしお客様のニーズに合うとお感じになられましたら、ご購入のオプションもございます。IronPDFの商用ライセンスまた、IronPDFの機能をあなたのプロジェクトで使い続けることができるように、ライセンス版に付属する完全な利点とサポートを提供し、PDF関連の機能をあなたのアプリケーションにスムーズに統合できるようにします。

< 以前
エンティティフレームワーク C#(開発者向けの仕組み)
次へ >
C# Webフレームワーク(開発者向けの動作方法)