{"id":30880632,"url":"https://github.com/sator-imaging/tdoubles","last_synced_at":"2026-02-18T06:01:09.527Z","repository":{"id":312784249,"uuid":"1047931990","full_name":"sator-imaging/TDoubles","owner":"sator-imaging","description":"C# Source Generator for Strongly-Typed Mocks and Fakes","archived":false,"fork":false,"pushed_at":"2026-01-10T04:40:41.000Z","size":382,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-20T23:26:58.064Z","etag":null,"topics":["roslyn-generator","source-generator","unit-testing"],"latest_commit_sha":null,"homepage":"https://sator-imaging.github.io/TDoubles/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sator-imaging.png","metadata":{"files":{"readme":"README.ja.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["sator-imaging"]}},"created_at":"2025-08-31T14:57:12.000Z","updated_at":"2026-01-10T04:40:45.000Z","dependencies_parsed_at":"2025-09-19T04:15:47.855Z","dependency_job_id":"4ec52b7e-f298-4f30-a88e-7e58a862f0ea","html_url":"https://github.com/sator-imaging/TDoubles","commit_stats":null,"previous_names":["sator-imaging/tdoubles"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/sator-imaging/TDoubles","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sator-imaging%2FTDoubles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sator-imaging%2FTDoubles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sator-imaging%2FTDoubles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sator-imaging%2FTDoubles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sator-imaging","download_url":"https://codeload.github.com/sator-imaging/TDoubles/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sator-imaging%2FTDoubles/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29569994,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-18T04:18:28.490Z","status":"ssl_error","status_checked_at":"2026-02-18T04:13:49.018Z","response_time":162,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["roslyn-generator","source-generator","unit-testing"],"created_at":"2025-09-08T07:10:09.158Z","updated_at":"2026-02-18T06:01:09.518Z","avatar_url":"https://github.com/sator-imaging.png","language":"C#","funding_links":["https://github.com/sponsors/sator-imaging"],"categories":[],"sub_categories":[],"readme":"[![nuget](https://img.shields.io/nuget/vpre/SatorImaging.TDoubles)](https://www.nuget.org/packages/SatorImaging.TDoubles)\n[![build](https://github.com/sator-imaging/TDoubles/actions/workflows/test.yml/badge.svg)](https://github.com/sator-imaging/TDoubles/actions/workflows/test.yml)\n\u0026nbsp;\n[![DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/sator-imaging/TDoubles)\n\n[🇺🇸 English](./README.md)\n\u0026nbsp; ❘ \u0026nbsp;\n[🇯🇵 日本語版](./README.ja.md)\n\u0026nbsp; ❘ \u0026nbsp;\n[🇨🇳 简体中文版](./README.zh-CN.md)\n\n\n![Hero](https://raw.githubusercontent.com/sator-imaging/TDoubles/main/GitHub-SocialPreview.png)\n\n`TDoubles` は、コンパイル時にモックラッパークラスを作成することで単体テストに革命をもたらす強力な C# ソースジェネレーターです。従来のモックフレームワークのように複雑なランタイムリフレクションやプロキシ生成に依存するのではなく、このジェネレーターはコンパイル中にクリーンで読みやすい C# コードを生成し、カスタマイズ可能な動作でターゲット型をラップします。\n\n\n\n## ✨ 従来のモックフレームワークとの比較\n\n| 機能 | TDoubles | 従来のフレームワーク (Moq, NSubstitute) |\n|---------|---------------------------|-------------------------------------------|\n| **パフォーマンス** | ゼロランタイムオーバーヘッド、コンパイル時生成 | ランタイムリフレクションとプロキシ作成 |\n| **型安全性** | 完全なコンパイル時チェックと IntelliSense | ランタイム構成、限定的な IntelliSense |\n| **ジェネリックサポート** | 制約を含む完全なサポート | 限定的なジェネリック型サポート |\n| **セットアップの複雑さ** | 単一属性、最小限の構成 | 複雑な流れるような API とセットアップ式 |\n| **デバッグ** | 生成されたコードは読みやすくデバッグ可能 | プロキシオブジェクトはデバッグが困難な場合がある |\n\n\n\n\n\n# ⚡ クイックスタート\n\n`[Mock]` 属性を部分クラスに適用するだけで、残りはジェネレーターが処理します。\n\n```cs\nusing TDoubles;\n\npublic interface IDataService\n{\n    string GetData(int id);\n    void SaveData(string data);\n}\n\n[Mock(typeof(IDataService))]   // 👈\npartial class DataServiceMock\n{\n    // 実装は自動的に生成されます\n}\n```\n\n以下に、コードでモックを使用する方法を示します。\n\n```cs\n// モックを作成\nvar mockService = new DataServiceMock();\n\n// テストのために動作をオーバーライド\nmockService.MockOverrides.GetData = (id) =\u003e $\"MockData_{id}\";\n//          ~~~~~~~~~~~~~\n\nstring mockData = mockService.GetData(123); // \"MockData_123\" を返します\n```\n\n実際の実装に委譲し、モックの部分的な動作をオーバーライドできます。\n\n```cs\nvar mock = new DataServiceMock(new ConcreteDataService());\n\n// デフォルトの動作を使用 (実際のサービスに委譲)\nvar realData = mock.GetData(123);\n\n// テストのために部分的な動作をオーバーライド\nmock.MockOverrides.SaveData = (data) =\u003e Console.WriteLine($\"Saved: {data}\");\nmock.SaveData(realData);\n```\n\n最新の実際の実装と連携して、デバッグ目的でフェイク動作を実装します。\n\n```cs\n[Mock(typeof(IFoo), nameof(IFoo.Save), nameof(IFoo.Load))]\npartial class FooFake\n{\n    public void Save() =\u003e File.WriteAllText(\"...\", JsonUtility.ToJson(this, true));\n    public void Load() =\u003e JsonUtility.FromJsonOverwrite(File.ReadAllText(\"...\"), this);\n}\n\n// Save と Load を除く最新の ConcreteFoo 実装に委譲\nvar fake = new FooFake(new ConcreteFoo());\n```\n\n## ジェネリック型サポート\n\n`TDoubles` は、アンバウンドおよびクローズドコンストラクトジェネリックの両方でジェネリック型モックをサポートします。\n\n```cs\n[Mock(typeof(IList\u003cint\u003e))]\npartial class ListIntMock {}\n\n// TKey の適切な型制約が自動的に生成され、\n// 型パラメーター名の不一致も解決されます\n[Mock(typeof(IDictioanry\u003c,\u003e))]\npartial class DictionaryMock\u003cT, U\u003e {}\n```\n\n## 効率的なコールバックサポート\n\n各モックメンバー呼び出しに対してカスタムコールバックを実装するための効率的な拡張ポイントがあります。\n\n\u003e [!TIP]\n\u003e C# の仕様として、`partial void` メソッド呼び出しは、モッククラス宣言でメソッド本体が実装されていない場合、ビルドされたアセンブリから完全に削除されます。\n\u003e \n\u003e https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/partial-member\n\n```cs\n[Mock(typeof(IList\u003c\u003e))]\npartial class ListSpy\u003cT\u003e  // 🕵 \u003c 容疑者を調査！\n{\n    readonly Dictionary\u003cstring, int\u003e _callCountByName = new();\n\n    // object?[] インスタンスを割り当てずに\n    partial void OnWillMockCall(string memberName)\n    {\n        if (!_callCountByName.TryGetValue(memberName, out var current))\n        {\n            current = 0;\n        }\n        _callCountByName[memberName] = current + 1;\n    }\n\n    // 別のオーバーロードは、モックメンバーに渡された引数を受け取ることができます\n    // * パラメーターなしのメンバーには Array.Empty\u003cobject\u003e() が使用されます\n    partial void OnWillMockCall(string memberName, object?[] args)\n    {\n        // メソッドのオーバーロードを決定する方法\n        if (memberName == \"Add\")\n        {\n            if (args[0] is T)\n            {\n                Console.WriteLine(\"Add(T item) が呼び出されました。\");\n            }\n            else\n            {\n                Console.WriteLine(\"Add(object item) が呼び出されました。\");\n            }\n        }\n    }\n}\n```\n\n## `Mock` 属性オプション\n\n生成されるモックメンバーを選択するオプションがあります。\n\n```cs\n// 内部型、インターフェース、メンバーをモック生成に含める\n[Mock(typeof(Foo), IncludeInternals = true)]\npartial class FooMock { }\n\n// 指定されたメンバーをモック生成から除外 (メンバーが見つからなくてもエラーなし)\n[Mock(typeof(Foo), \"ToString\", \"Foo\", \"Bar\", IncludeInternals = false)]\npartial class FooMockWithoutToStringOverride\n{\n    // 除外された 'ToString' を必要に応じて再実装できます\n    public override string ToString() =\u003e base.ToString() ?? \"\u003cNULL\u003e\";\n}\n```\n\n# はじめに\n\nこのジェネレーターは、`[Mock]` 属性でマークされた型を分析し、元の実装に委譲しながら、シンプルで厳密に型付けされた API を介してオーバーライド機能を提供する対応するモッククラスを生成することで機能します。このアプローチにより、リフレクションベースのモックのパフォーマンスオーバーヘッドが排除され、完全な型安全性と IntelliSense サポートが維持されます。\n\n## 主な利点\n\n- **ゼロランタイムオーバーヘッド**: モッククラスはコンパイル時に生成されるため、リフレクションコストが排除され、テスト実行パフォーマンスが向上します。\n- **完全な型安全性**: 生成されたモックは、完全な IntelliSense サポート、コンパイル時チェック、リファクタリングの安全性を備えています。\n- **最小限のセットアップ**: NuGet パッケージを追加し、`[Mock]` 属性を部分クラスに適用するだけで、残りはジェネレーターが処理します。\n- **普遍的な互換性**: インターフェース、クラス、レコード、レコード構造体、通常の構造体、静的クラスを含むすべての主要な C# 型コンストラクトをサポートします。\n- **高度なジェネリックサポート**: 型制約、ネストされたジェネリック、ジェネリックメソッドのオーバーロードを含む複雑なジェネリックシナリオを処理します。\n- **内部メンバーアクセス**: オプションの `IncludeInternals` 設定により、包括的なテストのために内部メンバーのモックが可能です。\n- **クリーンな生成コード**: 人間が読みやすく、デバッグ可能なモック実装を生成し、コードベースとシームレスに統合します。\n\n## ユースケース\n\nTDoubles ジェネレーターは、次のようなシナリオで優れています。\n\n- **高性能テスト**: テスト実行速度が重要で、リフレクションオーバーヘッドが許容できない場合。\n- **レガシーコードテスト**: インターフェースで設計されていない既存のクラスや構造体をモックする場合。\n- **静的メソッドテスト**: モックラッパーを介して静的メソッドをテスト可能なインスタンスメソッドに変換する場合。\n- **レコードと構造体のモック**: 従来のフレームワークでは困難な値型と不変レコードをテストする場合。\n- **複雑なジェネリックテスト**: 複数の型パラメーターと制約を持つジェネリック型をモックする場合。\n- **内部 API テスト**: 内部メンバーを公開せずにテストする場合。\n\n## 仕組み\n\n1. **ターゲット型をマーク**: `[Mock(typeof(TargetType))]` 属性を部分クラスに適用します。\n2. **コンパイル時生成**: ソースジェネレーターがターゲット型を分析し、モック実装を作成します。\n3. **オーバーライドによる委譲**: 生成されたモックは、カスタム動作のために `MockOverrides` を提供しながら、元のインスタンスに委譲します。\n4. **自信を持ってテスト**: 完全な型安全性とパフォーマンスで、生成されたモックをテストで使用します。\n\n### 委譲ロジック\n\n以下は委譲の擬似コードです。実際のコードは、`ref` および `out` パラメーター修飾子をサポートする必要があるため、より複雑です。\n\n```cs\npublic string GetData(int id)\n{\n    // 値型または null 許容参照型の場合は 'default' を返し、それ以外の場合はスローします\n    return MockOverrides.GetData?.Invoke(id)\n        ?? _target?.GetData(id)\n        ?? throw new TDoublesException(...);\n}\n```\n\n### 生成されたモック構造\n\nモッククラスを作成すると、ジェネレーターはいくつかのメンバーを追加します。\n\n```csharp\n[Mock(typeof(IUserService))]\npartial class UserServiceMock\n{\n    // ソースジェネレーターによって生成されます:\n\n    // ターゲットインスタンスを受け取るコンストラクター\n    public UserServiceMock(IUserService? target = default) { }\n\n    // 基になるターゲットへのアクセス\n    public IUserService? MockTarget { get; }\n\n    // 統合コールバック\n    partial void OnWillMockCall(string memberName);\n    partial void OnWillMockCall(string memberName, object?[] args);\n\n    // オーバーライド構成オブジェクト\n    public sealed class MockOverrideContainer { }\n    public MockOverrideContainer MockOverrides { get; }\n\n    // すべてのインターフェース/クラスメンバーが実装されます\n    public string GetUserName(int userId) { /* 生成された実装 */ }\n    public Task\u003cbool\u003e DeleteUser(int userId) { /* 生成された実装 */ }\n    // ... など\n}\n```\n\n# インストール\n\n## NuGet パッケージのインストール\n\n### パッケージマネージャーコンソール\n\n```powershell\nInstall-Package SatorImaging.TDoubles\n```\n\n### .NET CLI\n\n```bash\ndotnet add package SatorImaging.TDoubles\n```\n\n### PackageReference (手動)\n\nプロジェクトファイル (`.csproj`) に以下を追加します。\n\n```xml\n\u003cPackageReference Include=\"SatorImaging.TDoubles\" Version=\"1.0.0\" /\u003e\n```\n\n## システム要件\n\n- **.NET Framework**: .NET Standard 2.0 以降\n- **C# 言語バージョン**: C# 7.3 以降\n- **互換性のあるランタイム**:\n    - .NET Framework 4.6.1+\n    - .NET Core 2.0+\n    - .NET 5.0+\n    - Unity 2022.3.12f1 以降\n\n## セットアップと構成\n\n### 基本的なセットアップ\n\n1. 上記のいずれかの方法で NuGet パッケージをインストールします。\n2. ソースジェネレーターを有効にするためにプロジェクトをリビルドします。\n3. `[Mock]` 属性を持つ部分クラスを作成してモックを生成します。\n\n### プロジェクト構成\n\n追加のプロジェクト構成は不要です。パッケージがインストールされると、ソースジェネレーターは自動的にアクティブになり、コンパイル中にモッククラスを生成します。\n\n### 検証\n\nインストールが成功したことを確認するには:\n\n1. プロジェクトにシンプルなモッククラスを追加します。\n   ```csharp\n   using TDoubles;\n   \n   public interface ITestService\n   {\n       string GetMessage();\n   }\n   \n   [Mock(typeof(ITestService))]\n   partial class TestServiceMock\n   {\n       // モック実装はここに生成されます\n   }\n   ```\n2. プロジェクトをビルドします。\n3. コンパイルエラーが発生せず、モッククラスが生成されていることを確認します。\n\n### IDE サポート\n- **Visual Studio**: 生成されたモッククラスの完全な IntelliSense サポート\n- **Visual Studio Code**: C# 拡張機能で動作\n- **JetBrains Rider**: コード補完を含む完全なサポート\n- **コマンドライン**: `dotnet build` および `msbuild` で動作\n\n# 基本的な使用法\n\nこのセクションでは、`TDoubles` の使用を開始するためのステップバイステップの例を示します。すべての例は完全であり、プロジェクトですぐに使用できます。\n\n## 前提条件\n\nTDoubles ジェネレーターを使用する前に、モッククラスが次の要件を満たしていることを確認してください。\n\n1. **部分クラス**: モッククラスは `partial` として宣言する必要があります。\n2. **Mock 属性**: `[Mock(typeof(TargetType))]` を部分クラスに適用します。\n3. **名前空間**: `using TDoubles;` を含めます。\n4. **可視性**: 任意の可視性修飾子 (public, internal など) を使用できます。生成されたメンバーは同じ可視性を継承します。\n\n## シンプルなインターフェースモック\n\n最も一般的なシナリオは、依存性注入テストのためのインターフェースのモックです。\n\n### 例: ユーザーサービスインターフェース\n\n```csharp\nusing TDoubles;\nusing System;\nusing System.Threading.Tasks;\n\n// インターフェースを定義\npublic interface IUserService\n{\n    string GetUserName(int userId);\n    Task\u003cbool\u003e DeleteUser(int userId);\n    bool IsUserActive(int userId);\n}\n\n// 部分モッククラスを作成\n[Mock(typeof(IUserService))]\npartial class UserServiceMock\n{\n    // ソースジェネレーターがここに完全な実装を作成します\n}\n\n// テストでの使用例\nclass Program\n{\n    static void Main()\n    {\n        // 委譲のための具体的な実装を作成\n        var realService = new ConcreteUserService();\n        \n        // 実際のサービスを基になるターゲットとしてモックを作成\n        var mockService = new UserServiceMock(realService);\n        \n        Console.WriteLine(\"=== デフォルトの動作 (実際のサービスに委譲) ===\");\n        Console.WriteLine($\"ユーザー名: {mockService.GetUserName(123)}\");\n        Console.WriteLine($\"アクティブ: {mockService.IsUserActive(123)}\");\n        \n        Console.WriteLine(\"\\n=== オーバーライドによるカスタム動作 ===\");\n        \n        // テストのために特定のメソッドをオーバーライド\n        mockService.MockOverrides.GetUserName = (userId) =\u003e $\"MockUser_{userId}\";\n        mockService.MockOverrides.IsUserActive = (userId) =\u003e userId \u003e 100;\n        \n        Console.WriteLine($\"ユーザー名 (オーバーライド): {mockService.GetUserName(123)}\");\n        Console.WriteLine($\"アクティブ (オーバーライド): {mockService.IsUserActive(50)}\");\n        Console.WriteLine($\"アクティブ (オーバーライド): {mockService.IsUserActive(150)}\");\n        \n        // 必要に応じて基になる実際のサービスにアクセス\n        Console.WriteLine($\"実際のサービス: {mockService.MockTarget.GetUserName(123)}\");\n    }\n}\n\n// デモンストレーションのための具体的な実装\npublic class ConcreteUserService : IUserService\n{\n    public string GetUserName(int userId) =\u003e $\"RealUser_{userId}\";\n    public async Task\u003cbool\u003e DeleteUser(int userId) =\u003e await Task.FromResult(true);\n    public bool IsUserActive(int userId) =\u003e true;\n}\n```\n\n## 継承によるクラスモック\n\n継承シナリオと仮想メソッドのオーバーライドをテストするために、具象クラスをモックします。\n\n### 例: 仮想メソッドを持つサービスクラス\n\n```csharp\nusing TDoubles;\nusing System;\n\n// 仮想メソッドを持つ基本サービスクラス\npublic class DatabaseService\n{\n    public virtual string GetConnectionString() =\u003e \"Server=localhost;Database=prod;\";\n    public virtual void SaveData(string data) =\u003e Console.WriteLine($\"Saving to database: {data}\");\n    public virtual int GetRecordCount() =\u003e 1000;\n    \n    // 非仮想メソッド (ラップされるがオーバーライド不可)\n    public string GetServiceName() =\u003e \"DatabaseService\";\n}\n\n// クラスのモックを作成\n[Mock(typeof(DatabaseService))]\npartial class DatabaseServiceMock\n{\n    // 生成された実装はすべてのパブリックメソッドをラップします\n}\n\n// 使用例\nclass Program\n{\n    static void Main()\n    {\n        // 実際のサービスインスタンスを作成\n        var realService = new DatabaseService();\n        \n        // モックラッパーを作成\n        var mockService = new DatabaseServiceMock(realService);\n        \n        Console.WriteLine(\"=== デフォルトの動作 ===\");\n        Console.WriteLine($\"接続: {mockService.GetConnectionString()}\");\n        Console.WriteLine($\"サービス名: {mockService.GetServiceName()}\");\n        Console.WriteLine($\"レコード数: {mockService.GetRecordCount()}\");\n        mockService.SaveData(\"test data\");\n        \n        Console.WriteLine(\"\\n=== テストシナリオのオーバーライド ===\");\n        \n        // テストシナリオのためにオーバーライド\n        mockService.MockOverrides.GetConnectionString = () =\u003e \"Server=testserver;Database=test;\";\n        mockService.MockOverrides.GetRecordCount = () =\u003e 0; // 空のデータベースをシミュレート\n        mockService.MockOverrides.SaveData = (data) =\u003e Console.WriteLine($\"テストモード: '{data}' を保存します\");\n        \n        Console.WriteLine($\"テスト接続: {mockService.GetConnectionString()}\");\n        Console.WriteLine($\"テストレコード数: {mockService.GetRecordCount()}\");\n        mockService.SaveData(\"test data\");\n        \n        // 非仮想メソッドは引き続き機能しますが、元のものに委譲します\n        Console.WriteLine($\"サービス名 (常に委譲): {mockService.GetServiceName()}\");\n    }\n}\n```\n\n## 継承とインターフェースの実装\n\n基本クラスから継承し、インターフェースを実装するモッククラス。\n\n### 例: 複雑なサービス階層\n\n```csharp\nusing TDoubles;\nusing System;\n\n// インターフェース定義\npublic interface INotificationService\n{\n    void SendNotification(string message);\n    bool IsServiceAvailable();\n}\n\n// 仮想メソッドを持つ基本クラス\npublic class BaseService\n{\n    public virtual string GetServiceType() =\u003e \"Base\";\n    public virtual void Initialize() =\u003e Console.WriteLine(\"基本初期化\");\n}\n\n// 継承し、インターフェースを実装する具象クラス\npublic class EmailService : BaseService, INotificationService\n{\n    public override string GetServiceType() =\u003e \"Email\";\n    public override void Initialize() =\u003e Console.WriteLine(\"メールサービス初期化\");\n    \n    public void SendNotification(string message) =\u003e Console.WriteLine($\"メール: {message}\");\n    public bool IsServiceAvailable() =\u003e true;\n}\n\n// 具象クラスをモック\n[Mock(typeof(EmailService))]\npartial class EmailServiceMock\n{\n    // 継承されたメソッドとインターフェースの実装の両方をモックします\n}\n\n// 使用例\nclass Program\n{\n    static void Main()\n    {\n        var realService = new EmailService();\n        var mockService = new EmailServiceMock(realService);\n        \n        Console.WriteLine(\"=== 継承されたメソッドのテスト ===\");\n        Console.WriteLine($\"サービスタイプ: {mockService.GetServiceType()}\");\n        mockService.Initialize();\n        \n        Console.WriteLine(\"\\n=== インターフェースメソッドのテスト ===\");\n        mockService.SendNotification(\"Hello World\");\n        Console.WriteLine($\"利用可能: {mockService.IsServiceAvailable()}\");\n        \n        Console.WriteLine(\"\\n=== オーバーライドによるテスト ===\");\n        \n        // 継承されたメソッドをオーバーライド\n        mockService.MockOverrides.GetServiceType = () =\u003e \"MockEmail\";\n        mockService.MockOverrides.Initialize = () =\u003e Console.WriteLine(\"モック初期化\");\n        \n        // インターフェースメソッドをオーバーライド\n        mockService.MockOverrides.SendNotification = (msg) =\u003e Console.WriteLine($\"モックメール: {msg}\");\n        mockService.MockOverrides.IsServiceAvailable = () =\u003e false;\n        \n        Console.WriteLine($\"サービスタイプ: {mockService.GetServiceType()}\");\n        mockService.Initialize();\n        mockService.SendNotification(\"テストメッセージ\");\n        Console.WriteLine($\"利用可能: {mockService.IsServiceAvailable()}\");\n    }\n}\n```\n\n# 高度な使用法\n\nジェネリック型、静的クラス、レコード、構造体、内部メンバーアクセスを含む高度なシナリオについては、[高度な使用法ガイド](docs/advanced-usage.md) を参照してください。\n\n# テスト例\n\nMSTest、NUnit を使用した包括的なテスト例とパフォーマンス比較については、[テスト例ガイド](docs/testing-examples.md) を参照してください。\n\n# 技術ノート\n\n## `record` および `record struct`\n\n- 常に `IEquatable\u003cMOCK_TARGET_RECORD\u003e` と `MockOverrides.MockTargetRecord_Equals` を実装します。\n    - これは `IEquatable\u003cGENERATED_MOCK\u003e` *ではない* ことに注意してください。\n- `bool Equals(object?)` はオーバーライドできません。\n\n# 既知の制限事項とサポートされていないシナリオ\n\n## ジェネリックメソッドの型パラメーター\n\nメソッドが型レベルのパラメーターではなくメソッドレベルの型パラメーターを使用する場合、`MockOverrides` はメソッドレベルの型パラメーターの代わりに `object` を使用します。\n\n```cs\n// 生成されたモックは型レベルのパラメーター T を持ちます\npartial class Mock\u003cT\u003e\n{\n    // T と TMethod 型パラメーターを持つ生成されたモックメソッド\n    public TMethod GenericMethod\u003cT, TMethod\u003e(T input) { ... }\n\n    // \u003cTMethod\u003e はこのクラスに追加できますが、型レベルのパラメーターとしても公開する必要があります...\n    public sealed class MockOverrideContainer\n    {\n        // 型レベルのパラメーター T が使用されますが、TMethod は object にシャドウされます\n        public Func\u003cT, object\u003e GenericMethod { get; set; }\n        //             ~~~~~~ TMethod ではない\n    }\n}\n```\n\n\u003e [!NOTE]\n\u003e 生成されたモックメソッドは、モックターゲットと同様に `TMethod` を返します。内部的には、モックメソッドはオーバーライドからの `object` 結果を返すときに `TMethod` にキャストします。\n\n## 型システムの制限\n\n**サポートされていない型:**\n- 列挙型 (代わりにラッパークラスを使用)\n- デリゲートと関数ポインター\n- プリミティブ型 (`int`、`string` など)\n- 静的コンストラクターのみを持つ静的クラス\n- 実装を必要とする純粋仮想メソッドを持つ抽象クラス\n- `object`、`ValueType`、`Enum`、および `Span\u003cT\u003e` などのその他の特殊な型\n\n## 型制約の制限\n\n**サポートされていない制約:**\n- `where T : default`\n- `where T : allows ref struct`\n\n## 戻り値の型の制限\n\n**サポートされていない型:**\n- `ref` 戻り値の型\n\n## 属性の制限\n\n型、メソッド、プロパティなどに対する属性は、生成されたモックでは保持されません。\n\n## メソッドとプロパティの制限\n\n**サポートされていないメンバー:**\n- 一部の複雑なシナリオでの `ref` および `out` パラメーター (?)\n- ~~`__arglist` (可変引数) を持つメソッド~~ \n- ~~名前の競合がある明示的なインターフェース実装~~ \n- ~~複雑な getter/setter アクセシビリティの組み合わせを持つプロパティ~~ \n\n**部分的なサポート:**\n\n```csharp\npublic interface IService\n{\n    // ✅ 完全サポート\n    string GetData(int id);\n    Task\u003cbool\u003e ProcessAsync(string data);\n    \n    // ⚠️ 限定的なサポート - 正しくオーバーライドされない場合があります\n    ref int GetReference();\n    void ProcessData(__arglist);\n}\n```\n\n## ジェネリックメソッドの制限\n\n一部の有効な型制約は正しく変換されません。この型制約の特殊なケースをサポートする予定はありません。\n\n\u003e 注: `override` メソッドは、`class` と `struct` を除いて型制約を持つことはできません。\n\n```cs\n// (M, N?) を返す抽象メソッド宣言、where M : N? 制約付き\npublic abstract (M t, N? u) TypeArgMappingNullable_Abstract\u003cM, N\u003e() where M : N?;\n\n// 期待される (有効な) 戻り値の型は (M, N)\npublic override (M t, N u) TypeArgMappingNullable_Abstract\u003cM, N\u003e() { }\n\n// しかし、(M, N?) が返される\npublic override (M t, N? u) TypeArgMappingNullable_Abstract\u003cM, N\u003e() { }\n```\n\n## 継承とインターフェースの制限\n\n**複数のインターフェース実装:**\n- ~~サポートされていますが、明示的なインターフェース実装で名前の競合が発生する可能性があります~~ \n- ダイヤモンド継承パターンは、メソッド解決の問題を引き起こす可能性があります。\n\n**仮想メソッドのオーバーライド:**\n- ~~クラスモックでは `virtual` および `abstract` メソッドのみをオーバーライドできます~~ \n- `sealed` メソッドはオーバーライドできません (元のものに委譲されます)。\n\n## プラットフォームとフレームワークの制限\n\n**フレームワークサポート:**\n- .NET Standard 2.0 以降が必要\n- ソースジェネレーターには C# 7.3 以降が必要\n- 一部の高度な C# 11+ 機能は完全にサポートされていない場合があります\n\n**IDE 統合:**\n- 新しく生成されたモックの IntelliSense が遅れる場合があります\n- 一部の IDE では、生成されたコードを認識するためにリビルドが必要な場合があります\n- 生成されたコードのデバッグでは、最適化された/合成されたコードが表示される場合があります\n\n# 貢献\n\nコミュニティからの貢献を歓迎し、感謝いたします！バグの修正、機能の追加、ドキュメントの改善、フィードバックの提供など、皆様の貢献は TDoubles をすべての人にとってより良いものにするのに役立ちます。\n\n[CONTRIBUTING.md](CONTRIBUTING.md) を参照してください。\n\n# 行動規範\n\n私たちは、すべての貢献者にとって歓迎的で包括的な環境を提供することにコミットしています。すべてのやり取りにおいて、敬意を払い、プロフェッショナルであることを心がけてください。\n\n# サポートとコミュニティ\n\n## ヘルプの取得\n\nこのトラブルシューティングガイドでカバーされていない問題に遭遇した場合は:\n\n1. **GitHub Issues を確認**: 既存の Issue で同様の問題を検索します。\n2. **最小限の再現を作成**: 問題を示す最小限のコード例を提供します。\n3. **ビルド出力を含める**: 関連するコンパイラエラーと警告を共有します。\n4. **環境を指定**: .NET バージョン、IDE、オペレーティングシステムの詳細を含めます。\n\n**サポートチャネル:**\n- [GitHub Discussions](https://github.com/sator-imaging/TDoubles/discussions) - 質問とコミュニティサポート\n- [GitHub Issues](https://github.com/sator-imaging/TDoubles/issues) - バグレポートと機能リクエスト\n\n## セキュリティ問題の報告\n\nセキュリティの脆弱性を発見した場合は、公開の Issue を作成するのではなく、メンテナーにメールでプライベートに報告してください。これにより、問題が広く知られる前に対応することができます。\n\n# プロジェクト情報\n\n## TODO: 協力者募集\n\n- 不足しているテスト\n    - `static` クラスのモック\n    - `sealed` オーバーライドされたメソッド\n    - `async` テスト\n    - `event` ゲッターとセッターのテスト\n    - `readonly struct` テスト\n    - `readonly record struct` テスト\n    - `Tuple` と `ValueTuple` テスト\n    - プロパティとインデクサーのアクセシビリティテスト (例: `{ get; private set; }` など)\n- 不足している機能\n    - `ref` 戻り値\n    - 属性の保持\n    - ネストされた型のサポート (例: `[Mock(typeof(Foo.Bar))]`)\n    - ネストされたジェネリック型のモック (例: `[Mock(typeof(Foo.NestedKeyValueStore\u003c,\u003e))]`)\n    - モックメンバーに適切な `\u003cinheritdoc cref=\"...\" /\u003e` を追加\n    - `default` および `allows ref struct` 型制約のサポート\n        - `default` 制約は、オーバーライドおよび明示的なインターフェース実装メソッドでのみ有効\n        - Unity エンジンサポートを維持しながら Roslyn の更新が必要\n    - 型パラメーターに関する診断エラーの出力\n- 最適化\n    - 可能な限り `ImmutableArray\u003cT\u003e` または `ImmutableList\u003cT\u003e` を使用\n    - 非効率な `StringBuilder` の使用を排除\n- リファクタリング\n    - FP プログラミング手法の排除\n        - 情報と動作をカプセル化するためにデータモデルをドメインモデルに変換\n        - 一貫性、堅牢性、保守性を確保するために、ブループリントから C# への変換をドメインモデルに集中\n        - コードベースに散らばっている重複する関数、制御フローなどを排除\n- オプション\n    - ~~各モックメンバーの呼び出し回数を記録する `MockCallCounts` を生成する新しい `Mock` 属性オプション~~ \n        - `volatile int` フィールドを宣言\n        - 生成されたモッククラスメンバーの先頭で `Interlocked.Increment(ref ...)` メソッドによってカウントをインクリメント\n\n## 作者とメンテナー\n\n**Sator Imaging**\n- GitHub: [@sator-imaging](https://github.com/sator-imaging)\n- プロジェクトリポジトリ: [sator-imaging/TDoubles](https://github.com/sator-imaging/TDoubles)\n\n## 謝辞\n\nコードの貢献、バグ報告、機能提案、コミュニティサポートを通じてこのプロジェクトの改善に協力してくださったすべての貢献者に感謝いたします。\n\n## ライセンス\n\nこのプロジェクトは **MIT ライセンス** の下でライセンスされています。\n\n### サードパーティライセンス\n\nこのプロジェクトは以下のサードパーティパッケージを使用しています。\n- **Microsoft.CodeAnalysis.CSharp** (MIT ライセンス)\n- **Microsoft.CodeAnalysis.Analyzers** (MIT ライセンス)\n\n---\n\n**\u0026copy; 2025 Sator Imaging. All rights reserved.**\n\nサポート、質問、または貢献については、[GitHub リポジトリ](https://github.com/sator-imaging/TDoubles) をご覧ください。\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsator-imaging%2Ftdoubles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsator-imaging%2Ftdoubles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsator-imaging%2Ftdoubles/lists"}