.NET ヘルプ

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

リーガン・パン
リーガン・パン
2023年10月29日
共有:

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

MOQとは何ですか?

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

MOQの主な機能

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

MOQの使い方はじめに

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

新しい C# プログラムを作成する

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

  1. Visual Studio を開き、「ファイル」 > 「新規作成」 > 「プロジェクト...」に進みます。

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

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

    たとえば、ATM(現金自動預け払い機)用のソフトウェアを開発していて、認証と引き出し機能をテストする必要があるとします。 ATM は 2 つのインターフェイス、IHostBankIHSMModule に依存しています。 私たちは、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);
}

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;
    }
}

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

では、MOQを使用して依存関係をモックし、ATMCashWithdrawalクラスのユニットテストを作成しましょう。

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

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

  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を使用してユニットテストを作成し、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.)
    }
}

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

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

ステップ3 テストの実行

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

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

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

  4. テスト結果を確認してください。 あなたが書いたテスト(WithdrawAmount\_ValidTransaction\_ReturnsTrue)が合格するのを確認する必要があります。

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

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

IronPDFの紹介

IronPDFのドキュメントと機能の概要は、開発者がアプリケーション内でPDFドキュメントを扱うことができる強力なC#ライブラリです。 さまざまな機能を提供し、HTML、画像、既存のPDFなど、さまざまなソースからPDFファイルを作成、修正、および変換できます。 前回のチュートリアルで説明したモックオブジェクトの概念と組み合わせると、IronPDFはユニットテストでPDFドキュメントを生成および操作するための貴重なツールとなります。

IronPDFの主な機能は、そのHTML to 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");
    }
}

例えば、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>";
    }
}

モック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());
    }

}

このテストコードでは、予想される出力を表すモックPDF (expectedPdf) を生成し、PDFGenerator によって生成されたPDF (actualPDF) と比較します。 両方のPDFの内容を抽出して、同じ内容であるかどうかを確認しました。

結論

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

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

注目すべきは、IronPDFがその機能を試すための無料試用版を提供していることです。 ニーズに合っている場合は、商用ライセンスを購入するオプションがあります。これにより、ライセンス版に付随するすべての利点とサポートを受けながら、プロジェクトでIronPDFの機能を継続して使用し、アプリケーションへのPDF関連機能の円滑な統合を保証します。

リーガン・パン
ソフトウェアエンジニア
レーガンはリーディング大学で電子工学の学士号を取得しました。Iron Softwareに入社する前の仕事では、一つのタスクに集中して取り組んでいました。Iron Softwareでは、営業、技術サポート、製品開発、マーケティングのいずれにおいても広範な業務に携わることが最も楽しいと感じています。彼は、Iron Softwareライブラリを開発者がどのように使用しているかを理解し、その知識を使ってドキュメントを継続的に改善し、製品を開発することを楽しんでいます。
< 以前
エンティティフレームワーク C#(開発者向けの仕組み)
次へ >
C# Webフレームワーク(開発者向けの動作方法)