{"id":19080423,"url":"https://github.com/seeminglyscience/mockingpsclassespoc","last_synced_at":"2025-04-30T06:10:22.550Z","repository":{"id":87373319,"uuid":"109527712","full_name":"SeeminglyScience/MockingPSClassesPoC","owner":"SeeminglyScience","description":"A proof of concept for mocking class methods created in PowerShell","archived":false,"fork":false,"pushed_at":"2017-11-04T20:29:20.000Z","size":11,"stargazers_count":11,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-30T06:10:04.350Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PowerShell","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/SeeminglyScience.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-11-04T20:25:21.000Z","updated_at":"2024-04-05T09:46:06.000Z","dependencies_parsed_at":"2023-03-27T13:04:54.455Z","dependency_job_id":null,"html_url":"https://github.com/SeeminglyScience/MockingPSClassesPoC","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/SeeminglyScience%2FMockingPSClassesPoC","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeeminglyScience%2FMockingPSClassesPoC/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeeminglyScience%2FMockingPSClassesPoC/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeeminglyScience%2FMockingPSClassesPoC/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SeeminglyScience","download_url":"https://codeload.github.com/SeeminglyScience/MockingPSClassesPoC/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251651231,"owners_count":21621716,"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":[],"created_at":"2024-11-09T02:23:34.267Z","updated_at":"2025-04-30T06:10:22.544Z","avatar_url":"https://github.com/SeeminglyScience.png","language":"PowerShell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PSClass Mock Proof of Concept\n\nThis module is a proof of concept for a potential way to add PowerShell class mocking functionality for\ntest scripts.  The demo is fully functional, though I have not done any extensive tests, only enough\nto know it works.  This module is intended to be a demonstration only.\n\nIf anyone wants to build this into a proper implementation feel free to reach out if you run into issues.\n\n## Pros\n\n- Fully mock any method in any PowerShell class, both static and instance\n- Mocks apply to existing instances as well as new instances\n- Mocks apply to all classes of the same name, even stale versions in older scopes\n- Mocks can be defined for classes that haven't been defined yet\n- Supports parameter filters\n- Mocks will persist even if called by compiled classes\n\n## Cons\n\n- The way mocking is done uses a significant amount of reflection to access PowerShell internals\n- Properties cannot be mocked.  This can be worked around by mocking the constructor\n- Compiler generated functions cannot be mocked.  These are created when you give a property a default\n  value.  This can be worked around by defining a constructor\n\n## How\n\nWhen a PowerShell class is defined there is another class created with it called a \"static helper\".\nThis class contains a `ScriptBlockMemberMethodWrapper` object for each method defined in the class.\nMocking is possible by replacing that wrapper with a new one that determines the method it was called\nfrom, evaluates parameter filters, and invokes the appropriate script block.\n\nWhen a mock is defined, the AppDomain is searched for matching PowerShell classes and replaces all\nmember wrappers with wrappers controlled by the module.  An `AssemblyLoad` event subscriber is registered\nto handle the mocking of classes loaded after the fact.  Because all of this is handled via static fields\nit doesn't matter when the class was loaded, what scope it was in, or what instances were already\ncreated.\n\n## Trying it out\n\n```powershell\ngit clone https://github.com/SeeminglyScience/MockingPSClassesPoC\nImport-Module ./MockingPSClassesPoC/module/MockingPSClassesPoC.psd1\n\nAdd-MethodMock MyClass MyMethod { return $this.MyProperty -replace 'not ' }\nclass MyClass {\n    [string] $MyProperty;\n\n    MyClass() {\n        $this.MyProperty = 'NotMocked'\n    }\n\n    [string] MyMethod() {\n        return $this.MyProperty\n    }\n}\n\n$instance = [MyClass]::new()\n$instance.MyMethod()\n# Mocked\nClear-MethodMock\n$instance.MyMethod()\n# Not Mocked\n\n. {\n    class MyClass {\n        [string] $MyProperty;\n\n        MyClass() {\n            $this.MyProperty = 'Definitely Not Mocked'\n        }\n\n        [string] MyMethod([string] $parameter) {\n            return $this.MyProperty\n        }\n    }\n\n    $newInstance = [MyClass]::new()\n}\n\nAdd-MethodMock MyClass MyMethod { return $this.MyProperty -replace 'not ' }\nAdd-MethodMock MyClass MyMethod { return 'Completely Mocked' } { $parameter -eq 'super mocked' }\n\n$newInstance.MyMethod('default mock')\n# Definitely Mocked\n$newInstance.MyMethod('super mocked')\n# Completely Mocked\n\n# Mock applies to the old instance too\n$instance.MyMethod()\n# Mocked\n\nAdd-MethodMock MyClass MyClass { $this.MyProperty = 'Mocked from the start' }\n[MyClass]::new()\n# MyProperty\n# ----------\n# Mocked from the start\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseeminglyscience%2Fmockingpsclassespoc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseeminglyscience%2Fmockingpsclassespoc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseeminglyscience%2Fmockingpsclassespoc/lists"}