{"id":13629635,"url":"https://github.com/HamedFathi/MockableStaticGenerator","last_synced_at":"2025-04-17T09:35:20.523Z","repository":{"id":90748344,"uuid":"315986481","full_name":"HamedFathi/MockableStaticGenerator","owner":"HamedFathi","description":"A C# source generator to make an interface and a class wrapper to test static and extension methods.","archived":false,"fork":false,"pushed_at":"2022-09-20T17:39:55.000Z","size":86,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-11-06T05:41:10.847Z","etag":null,"topics":["csharp","csharp-sourcegenerator","csharp9","dotnet","mock","mocking","sourcegenerator","test","testing"],"latest_commit_sha":null,"homepage":"https://hamedfathi.me/the-dotnet-world-csharp-source-generator/","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/HamedFathi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"github":"HamedFathi","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2020-11-25T15:54:22.000Z","updated_at":"2024-02-08T18:09:57.000Z","dependencies_parsed_at":"2024-01-06T02:09:51.213Z","dependency_job_id":null,"html_url":"https://github.com/HamedFathi/MockableStaticGenerator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HamedFathi%2FMockableStaticGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HamedFathi%2FMockableStaticGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HamedFathi%2FMockableStaticGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HamedFathi%2FMockableStaticGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HamedFathi","download_url":"https://codeload.github.com/HamedFathi/MockableStaticGenerator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223751320,"owners_count":17196613,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["csharp","csharp-sourcegenerator","csharp9","dotnet","mock","mocking","sourcegenerator","test","testing"],"created_at":"2024-08-01T22:01:15.399Z","updated_at":"2024-11-08T20:31:31.031Z","avatar_url":"https://github.com/HamedFathi.png","language":"C#","readme":"![encode](https://user-images.githubusercontent.com/8418700/140723471-a3529ea9-db8f-465e-9eaa-64e16fbb950f.png)\n\n## Problem\n\nI want to mock static or extensions methods. What should I do?\n\nSometimes I have those static methods inside my library and sometime they are in an external library like [Dapper](https://github.com/DapperLib/Dapper)\n\nDo you have any solution?\n\n## Solution\n\nA good, well-known solution is writing a wrapper.\n\nConsider the following example:\n\n```cs\npublic class MyClass\n{\n    public void LogMessage(string message)\n    {\n        Logger.Write(message);\n    }\n}\n\npublic class Logger\n{\n    public static void Write(string message)\n    {\n       //Write your code here to log data\n    }\n}\n```\n\nYou can use [Moq](https://github.com/moq/moq4) to mock non-static methods but it cannot be used to mock static methods, so what should I do if I want to mock `Logger.Write`?\n\n#### Create a wrapper class and interface\n\nMake an interface just like the signature of the static method\n\n```cs\npublic interface IWrapper\n{\n    void LogData(string message);\n}\n```\n\nImplement that interface and call the static method (`Logger.Write`) into the same non-static method.\n\n```cs\npublic class LogWrapper : IWrapper\n{\n    string _message = null;\n    public LogWrapper(string message)\n    {\n        _message = message;\n    }\n    public void LogData(string message)\n    {\n        _message = message;\n        Logger.Write(_message);\n    }\n}\n```\n\nNow you can use `IWrapper` and `LogWrapper` everywhere in your code and also make things mockable.\n\n```cs\nvar mock = new Mock\u003cIWrapper\u003e();\nmock.Setup(x =\u003e x.LogData(It.IsAny\u003cstring\u003e()));\nnew ProductBL(mock.Object).LogMessage(\"Hello World!\");\nmock.VerifyAll();\n```\n\n#### What is the wrong part with this solution?\n\nOf course, you can not do this for all static methods or for all external libraries. It is hard and tedious work. Maybe sometimes impossible!\n\n## MockableStaticGenerator\n\n`MockableStaticGenerator` is a C# code generator for making your static/extension methods even from an external library mockable just like above approach but automatically!\n\n#### How it works?\n\n* For internal usage\n\nIf you have a class with static methods inside it, put `[MockableStatic]` on top of the class\n\n```cs\n// For your class with some static methods.\n[MockableStatic]\npublic class Math\n{\n    public static int Add(int a, int b) { return a+b; }\n    public static int Sub(int a, int b) { return a+b; }\n}\n```\n\n* For external usage\n\nIf you have a class with static methods inside it but from somewhere else (an external library for example), you should introduce **type of** that class to the `[MockableStatic]`\n \n ```cs\n // For type of an external assembly with a lot of static methods\n // like 'Dapper.SqlMapper' class in Dapper external library.\n // It does not matter on top of what class it is, but Program class can be appropriate.\n[MockableStatic(typeof(Dapper.SqlMapper))]\nclass Program\n{\n    static void Main(string[] args)\n    {\n        // ...\n    }\n}\n ```\n \n#### How to call the generated interfaces and classes?\n\nThere are two naming conventions you should follow:\n\n* `I{CLASS_NAME}Wrapper` for the interface\n* `{CLASS_NAME}Wrapper` for the class\n\nand you can find them under this namespace.\n\n* namespace `MockableGenerated`\n    * `MockableGenerated.I{CLASS_NAME}Wrapper`\n    * `MockableGenerated.{CLASS_NAME}Wrapper`\n\n\n![image](https://user-images.githubusercontent.com/8418700/108617117-04539600-7429-11eb-804a-7c6e3241a799.png)\n![image](https://user-images.githubusercontent.com/8418700/108617134-1a615680-7429-11eb-9de0-b49006a50b6f.png)\n\n#### Attention\n\nYou **must** use the generated interfaces and classes **instead of** the originals to make your library/application testable and mockable.\n\n\u003chr/\u003e\n\n#### [Nuget](https://www.nuget.org/packages/MockableStaticGenerator)\n\n[![Open Source Love](https://badges.frapsoft.com/os/mit/mit.svg?v=102)](https://opensource.org/licenses/MIT)\n![Nuget](https://img.shields.io/nuget/v/MockableStaticGenerator)\n![Nuget](https://img.shields.io/nuget/dt/MockableStaticGenerator)\n\n```\nInstall-Package MockableStaticGenerator\ndotnet add package MockableStaticGenerator\n```\n\nFor more details read [this blog post](https://hamedfathi.me/the-dotnet-world-csharp-source-generator/).\n\n\u003chr/\u003e\n\n\u003cdiv\u003eIcons made by \u003ca href=\"https://www.freepik.com\" title=\"Freepik\"\u003eFreepik\u003c/a\u003e from \u003ca href=\"https://www.flaticon.com/\" title=\"Flaticon\"\u003ewww.flaticon.com\u003c/a\u003e\u003c/div\u003e\n","funding_links":["https://github.com/sponsors/HamedFathi"],"categories":["Source Generators","Do not want to test 112 ( old ISourceGenerator )"],"sub_categories":["Testing","1. [ThisAssembly](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ThisAssembly) , in the [EnhancementProject](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#enhancementproject) category"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHamedFathi%2FMockableStaticGenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FHamedFathi%2FMockableStaticGenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHamedFathi%2FMockableStaticGenerator/lists"}