{"id":13600248,"url":"https://github.com/bytedance/mockey","last_synced_at":"2026-01-08T08:18:54.099Z","repository":{"id":60331382,"uuid":"542049565","full_name":"bytedance/mockey","owner":"bytedance","description":"a simple and easy-to-use golang mock library","archived":false,"fork":false,"pushed_at":"2025-02-19T09:39:59.000Z","size":151,"stargazers_count":765,"open_issues_count":2,"forks_count":29,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-05-10T04:02:00.873Z","etag":null,"topics":["golang","mock","test","testing"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bytedance.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE-APACHE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2022-09-27T11:28:54.000Z","updated_at":"2025-05-09T09:59:20.000Z","dependencies_parsed_at":"2023-10-16T22:32:19.831Z","dependency_job_id":"363700af-2afe-441f-ae76-6224a114b83c","html_url":"https://github.com/bytedance/mockey","commit_stats":{"total_commits":34,"total_committers":8,"mean_commits":4.25,"dds":0.4411764705882353,"last_synced_commit":"a60edcc5b06dbc6d64d8f751a3dbf19ff49a9422"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytedance%2Fmockey","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytedance%2Fmockey/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytedance%2Fmockey/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bytedance%2Fmockey/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bytedance","download_url":"https://codeload.github.com/bytedance/mockey/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254159935,"owners_count":22024566,"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":["golang","mock","test","testing"],"created_at":"2024-08-01T18:00:33.318Z","updated_at":"2026-01-08T08:18:54.091Z","avatar_url":"https://github.com/bytedance.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Mockey\nEnglish | [中文](README_cn.md)\n\n[![Release](https://img.shields.io/github/v/release/bytedance/mockey)](https://github.com/bytedance/mockey/releases)\n[![License](https://img.shields.io/github/license/bytedance/mockey)](https://github.com/bytedance/mockey/blob/main/LICENSE-APACHE)\n[![Go Report Card](https://goreportcard.com/badge/github.com/bytedance/mockey)](https://goreportcard.com/report/github.com/bytedance/mockey)\n[![codecov](https://codecov.io/github/bytedance/mockey/graph/badge.svg?token=JKL3WSE3I3)](https://codecov.io/github/bytedance/mockey)\n[![OpenIssue](https://img.shields.io/github/issues/bytedance/mockey)](https://github.com/bytedance/mockey/issues)\n[![ClosedIssue](https://img.shields.io/github/issues-closed/bytedance/mockey)](https://github.com/bytedance/mockey/issues?q=is%3Aissue+is%3Aclosed)\n\nMockey is a simple and easy-to-use golang mock library, which can quickly and conveniently mock functions and variables. At present, it is widely used in the unit test writing of ByteDance services (7k+ repos) and is actively maintained. In essence, it rewrites function instructions at runtime similarly to [monkey](https://github.com/bouk/monkey) or [gomonkey](https://github.com/agiledragon/gomonkey).\n\nMockey makes it easy to replace functions, methods and variables with mocks reducing the need to specify all dependencies as interfaces.\n\u003e 1. Mockey requires **inlining and compilation optimization to be disabled** during compilation, or it won't work. See the [FAQs](#how-to-disable-inline-and-compile-optimization) for details.\n\u003e 2. It is strongly recommended to use it together with the [goconvey](https://github.com/smartystreets/goconvey) library in unit tests.\n\n## Install\n```\ngo get github.com/bytedance/mockey@latest\n```\n\n## Quick Guide\n### Simplest example\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"math/rand\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc main() {\n\tMock(rand.Int).Return(1).Build() // mock `rand.Int` to return 1\n\t\n\tfmt.Printf(\"rand.Int() always return: %v\\n\", rand.Int()) // Try if it's still random?\n}\n```\n\n### Unit test example\n```go\npackage main_test\n\nimport (\n\t\"math/rand\"\n\t\"testing\"\n\n\t. \"github.com/bytedance/mockey\"\n\t. \"github.com/smartystreets/goconvey/convey\"\n)\n\n// Win function to be tested, input a number, win if it's greater than random number, otherwise lose\nfunc Win(in int) bool {\n\treturn in \u003e rand.Int()\n}\n\nfunc TestWin(t *testing.T) {\n\tPatchConvey(\"TestWin\", t, func() {\n\t\tMock(rand.Int).Return(100).Build() // mock\n\t\t\n\t\tres1 := Win(101)                   // execute\n\t\tSo(res1, ShouldBeTrue)             // assert\n\t\t\n\t\tres2 := Win(99)         // execute\n\t\tSo(res2, ShouldBeFalse) // assert\n\t})\n}\n```\n\n## Features\n- Mock functions and methods\n    - Basic\n        - Simple / generic / variadic function or method (value or pointer receiver)\n        - Supporting hook function\n        - Supporting `PatchConvey` and `PatchRun` (automatically release mocks after each test case)\n        - Providing `GetMethod` to handle special cases (e.g., exported method of unexported types, unexported method, and methods in nested structs)\n    - Advanced\n        - Conditional mocking\n        - Sequence returning\n        - Decorator pattern (execute the original function after mocking)\n        - Goroutine filtering (inclusion, exclusion, targeting)\n        - Acquire `Mocker` for advanced usage (e.g., getting the execution times of target/mock function)\n- Mock variable\n    - Common variable\n    - Function variable\n\n## Compatibility\n### OS Support\n- Mac OS(Darwin)\n- Linux\n- Windows\n\n### Arch Support \n- AMD64\n- ARM64\n\n### Version Support \n- Go 1.13+\n\n## Basic Features\n### Simple function/method\nUse `Mock` to mock function/method, use `Return` to specify the return value, and use `Build` to make the mock effective:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc Foo(in string) string {\n\treturn in\n}\n\ntype A struct{}\n\nfunc (a A) Foo(in string) string { return in }\n\ntype B struct{}\n\nfunc (b *B) Foo(in string) string { return in }\n\nfunc main() {\n\t// mock function\n\tMock(Foo).Return(\"MOCKED!\").Build()\n\tfmt.Println(Foo(\"anything\")) // MOCKED!\n\n\t// mock method (value receiver)\n\tMock(A.Foo).Return(\"MOCKED!\").Build()\n\tfmt.Println(A{}.Foo(\"anything\")) // MOCKED!\n\n\t// mock method (pointer receiver)\n\tMock((*B).Foo).Return(\"MOCKED!\").Build()\n\tfmt.Println(new(B).Foo(\"anything\")) // MOCKED!\n    \n    // Tips: if the target has no return value, you still need to call the empty `Return()` or use `To` to customize the hook function.\n}\n```\n\n### Generic function/method\n\u003e Starting from v1.3.0, `Mock` experimentally adds the ability to automatically identify generics (for go1.20+), you can use `Mock` to directly replace `MockGeneric`\n\nUse `MockGeneric` to mock generic function/method:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc FooGeneric[T any](t T) T {\n\treturn t\n}\n\ntype GenericClass[T any] struct {\n}\n\nfunc (g *GenericClass[T]) Foo(t T) T {\n\treturn t\n}\n\nfunc main() {\n\t// mock generic function \n\tMockGeneric(FooGeneric[string]).Return(\"MOCKED!\").Build() // `Mock(FooGeneric[string], OptGeneric)` also works\n\tfmt.Println(FooGeneric(\"anything\"))                       // MOCKED!\n\tfmt.Println(FooGeneric(1))                                // 1 | Not working because of type mismatch!\n\n\t// mock generic method \n\tMockGeneric((*GenericClass[string]).Foo).Return(\"MOCKED!\").Build()\n\tfmt.Println(new(GenericClass[string]).Foo(\"anything\")) // MOCKED!\n}\n```\n\nAdditionally, Golang generics share implementation for different types with the same underlying type. For example, in `type MyString string`, `MyString` and `string` share one implementation. Therefore, mocking one type will interfere with the other.\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\ntype MyString string\n\nfunc FooGeneric[T any](t T) T {\n\treturn t\n}\n\nfunc main() {\n\tMockGeneric(FooGeneric[string]).Return(\"MOCKED!\").Build()\n\tfmt.Println(FooGeneric(\"anything\"))           // MOCKED!\n\tfmt.Println(FooGeneric[MyString](\"anything\")) // MOCKED! | This is due to interference after mocking the string type\n}\n```\n\nIn v1.3.1, this issue was resolved. We now support mocking generic functions/methods with the same gcshape but different actual types. The example above will behave more as expected:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\ntype MyString string\n\nfunc FooGeneric[T any](t T) T {\n\treturn t\n}\n\nfunc main() {\n\tmocker1 := MockGeneric(FooGeneric[string]).Return(\"MOCKED!\").Build()\n\tfmt.Println(FooGeneric(\"anything\"))           // MOCKED!\n\tfmt.Println(FooGeneric[MyString](\"anything\")) // anything | No longer interferes\n\tmocker2 := MockGeneric(FooGeneric[MyString]).Return(\"MOCKED2!\").Build()\n\tfmt.Println(FooGeneric(\"anything\"))           // MOCKED!\n\tfmt.Println(FooGeneric[MyString](\"anything\")) // MOCKED2! | No longer interferes\n\n\t// Note: If you need to manually release mockers, be sure to follow the \"last-in-first-out\" order, otherwise unexpected results such as crashes may occur\n\tmocker2.UnPatch()\n\tfmt.Println(FooGeneric(\"anything\"))           // MOCKED!\n\tfmt.Println(FooGeneric[MyString](\"anything\")) // anything\n\tmocker1.UnPatch()\n\tfmt.Println(FooGeneric(\"anything\"))           // anything\n\tfmt.Println(FooGeneric[MyString](\"anything\")) // anything\n}\n```\n\n### Variadic function/method\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc FooVariadic(in ...string) string {\n\treturn in[0]\n}\n\ntype A struct{}\n\nfunc (a A) FooVariadic(in ...string) string { return in[0] }\n\nfunc main() {\n\t// mock variadic function\n\tMock(FooVariadic).Return(\"MOCKED!\").Build()\n\tfmt.Println(FooVariadic(\"anything\")) // MOCKED!\n\n\t// mock variadic method\n\tMock(A.FooVariadic).Return(\"MOCKED!\").Build()\n\tfmt.Println(A{}.FooVariadic(\"anything\")) // MOCKED!\n}\n```\n\n### Supporting hook function\nUse `To` to specify the hook function:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc Foo(in string) string {\n\treturn in\n}\n\ntype A struct {\n\tprefix string\n}\n\nfunc (a A) Foo(in string) string { return a.prefix + \":\" + in }\n\nfunc main() {\n\t// NOTE: hook function must have the same function signature as the original function!\n\tMock(Foo).To(func(in string) string { return \"MOCKED!\" }).Build()\n\tfmt.Println(Foo(\"anything\")) // MOCKED!\n\n\t// NOTE: for method mocking, the receiver can be added to the signature of the hook function on your need (if the receiver is not used, it can be omitted, and mockey is compatible).\n\tMock(A.Foo).To(func(a A, in string) string { return a.prefix + \":inner:\" + \"MOCKED!\" }).Build()\n\tfmt.Println(A{prefix: \"prefix\"}.Foo(\"anything\")) // prefix:inner:MOCKED!\n}\n```\n\n### Supporting `PatchConvey` and `PatchRun`\n\u003e Starting from v1.4.1, `PatchRun` is supported\n\n`PatchConvey` and `PatchRun` are tools for managing mock lifecycles. They automatically release mocks after test cases or functions are executed, eliminating the need for `defer`. Both support nested usage, and each layer only releases its own internal mocks.\n\nApplicable scenarios comparison:\n- When you need to use the assertion features and test organization capabilities of the goconvey framework, it is recommended to use `PatchConvey`; the execution order of nested `PatchConvey` is the same as `Convey`, please refer to the goconvey related [documentation](https://github.com/smartystreets/goconvey/wiki/Execution-order)\n- When you don't need goconvey integration, it is recommended to use the more lightweight `PatchRun`\n\n`PatchConvey` example as follows:\n```go\npackage main_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/bytedance/mockey\"\n\t. \"github.com/smartystreets/goconvey/convey\"\n)\n\nfunc Foo(in string) string {\n\treturn \"ori:\" + in\n}\n\nfunc TestXXX(t *testing.T) {\n\tPatchConvey(\"TestXXX\", t, func() {\n\t\t// mock\n\t\tPatchConvey(\"mock 1\", func() {\n\t\t\tMock(Foo).Return(\"MOCKED-1!\").Build() // mock\n\t\t\tres := Foo(\"anything\")                // invoke\n\t\t\tSo(res, ShouldEqual, \"MOCKED-1!\")     // assert\n\t\t})\n\n\t\t// mock released\n\t\tPatchConvey(\"mock released\", func() {\n\t\t\tres := Foo(\"anything\")               // invoke\n\t\t\tSo(res, ShouldEqual, \"ori:anything\") // assert\n\t\t})\n\n\t\t// mock again\n\t\tPatchConvey(\"mock 2\", func() {\n\t\t\tMock(Foo).Return(\"MOCKED-2!\").Build() // mock\n\t\t\tres := Foo(\"anything\")                // invoke\n\t\t\tSo(res, ShouldEqual, \"MOCKED-2!\")     // assert\n\t\t})\n\t})\n\n\t// Tips: Like `Convey`, `PatchConvey` can be nested; each layer of `PatchConvey` will only release its own internal mocks\n}\n\n```\n\n`PatchRun` example as follows:\n```go\npackage main_test\n\nimport (\n\t\"testing\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc Foo(in string) string {\n\treturn \"ori:\" + in\n}\n\nfunc TestXXX(t *testing.T) {\n\t// mock\n\tPatchRun(func() {\n\t\tMock(Foo).Return(\"MOCKED-1!\").Build() // mock\n\t\tres := Foo(\"anything\")                // call\n\t\tif res != \"MOCKED-1!\" {\n\t\t\tt.Errorf(\"expected 'MOCKED-1!', got '%s'\", res)\n\t\t}\n\t})\n\n\t// mock released\n\tres := Foo(\"anything\") // call\n\tif res != \"ori:anything\" {\n\t\tt.Errorf(\"expected 'ori:anything', got '%s'\", res)\n\t}\n\n\t// mock again\n\tPatchRun(func() {\n\t\tMock(Foo).Return(\"MOCKED-2!\").Build() // mock\n\t\tres := Foo(\"anything\")                // call\n\t\tif res != \"MOCKED-2!\" {\n\t\t\tt.Errorf(\"expected 'MOCKED-2!', got '%s'\", res)\n\t\t}\n\t})\n\n\t// mock released\n\tres = Foo(\"anything\") // call\n\tif res != \"ori:anything\" {\n\t\tt.Errorf(\"expected 'ori:anything', got '%s'\", res)\n\t}\n}\n```\n\n### Providing `GetMethod` to handle special cases\nIn special cases where direct mocking is not possible or not effective, you can use `GetMethod` to get the corresponding method before mocking. Please ensure that the passed object is not nil.\n\nMock method through an instance (including interface type instances):\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\ntype A struct{}\n\nfunc (a A) Foo(in string) string { return in }\n\nfunc main() {\n\ta := new(A)\n\n\t// Mock(a.Foo) won't work, because `a` is an instance of `A`, not the type `A`\n\t// Tips: if the instance is an interface type, you can use it the same way\n\t// var ia interface{ Foo(string) string } = new(A)\n\t// Mock(GetMethod(ia, \"Foo\")).Return(\"MOCKED!\").Build()\n\tMock(GetMethod(a, \"Foo\")).Return(\"MOCKED!\").Build()\n\tfmt.Println(a.Foo(\"anything\")) // MOCKED!\n}\n```\n\nMock exported method of unexported types:\n```go\npackage main\n\nimport (\n\t\"crypto/sha256\"\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc main() {\n\t// `sha256.New()` returns an unexported `*digest`, whose `Sum` method is the one we want to mock\n\tMock(GetMethod(sha256.New(), \"Sum\")).Return([]byte{0}).Build()\n\n\tfmt.Println(sha256.New().Sum([]byte(\"anything\"))) // [0]\n\t\n\t// Tips: this is a special case of \"mocking methods through instances\", where the type corresponding to the instance is unexported\n}\n```\n\nMock unexported method:\n```go\npackage main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc main() {\n\t// `*bytes.Buffer` has an unexported `empty` method, which is the one we want to mock\n\tMock(GetMethod(new(bytes.Buffer), \"empty\")).Return(true).Build()\n\n\tbuf := bytes.NewBuffer([]byte{1, 2, 3, 4})\n\tb, err := buf.ReadByte()\n\tfmt.Println(b, err)      // 0 EOF | `ReadByte` calls `empty` method inside to check if the buffer is empty and return io.EOF\n}\n```\n\nMock methods in nested structs:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\ntype Wrapper struct {\n\tinner // nested struct\n}\n\ntype inner struct{}\n\nfunc (i inner) Foo(in string) string {\n\treturn in\n}\n\nfunc main() {\n\t// Mock(Wrapper.Foo) won't work, because the target should be `inner.Foo`\n\tMock(GetMethod(Wrapper{}, \"Foo\")).Return(\"MOCKED!\").Build() // or Mock(inner.Foo).Return(\"MOCKED!\").Build()\n\n\tfmt.Println(Wrapper{}.Foo(\"anything\")) // MOCKED! \n}\n```\n\n## Advanced features\n### Conditional mocking\nUse `When` to define multiple conditions:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc Foo(in string) string {\n\treturn \"ori:\" + in\n}\n\nfunc main() {\n\t// NOTE: condition function must have the same input signature as the original function!\n\tMock(Foo).\n\t\tWhen(func(in string) bool { return len(in) == 0 }).Return(\"EMPTY\").\n\t\tWhen(func(in string) bool { return len(in) \u003c= 2 }).Return(\"SHORT\").\n\t\tWhen(func(in string) bool { return len(in) \u003c= 5 }).Return(\"MEDIUM\").\n\t\tBuild()\n\n\tfmt.Println(Foo(\"\"))            // EMPTY\n\tfmt.Println(Foo(\"h\"))           // SHORT\n\tfmt.Println(Foo(\"hello\"))       // MEDIUM\n\tfmt.Println(Foo(\"hello world\")) // ori:hello world\n}\n```\n\n### Sequence returning\nUse `Sequence` to mock multiple return values:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc Foo(in string) string {\n\treturn in\n}\n\nfunc main() {\n\tMock(Foo).Return(Sequence(\"Alice\").Then(\"Bob\").Times(2).Then(\"Tom\")).Build()\n\tfmt.Println(Foo(\"anything\")) // Alice\n\tfmt.Println(Foo(\"anything\")) // Bob\n\tfmt.Println(Foo(\"anything\")) // Bob\n\tfmt.Println(Foo(\"anything\")) // Tom\n}\n```\n\n### Decorator pattern\nUse `Origin` to keep the original logic of the target after mock:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc Foo(in string) string {\n\treturn \"ori:\" + in\n}\n\nfunc main() {\n\t// `origin` will carry the logic of the `Foo` function\n\torigin := Foo\n\n\t// `decorator` will do some AOP around `origin`\n\tdecorator := func(in string) string {\n\t\tfmt.Println(\"arg is\", in)\n\t\tout := origin(in)\n\t\tfmt.Println(\"res is\", out)\n\t\treturn out\n\t}\n\n\tMock(Foo).Origin(\u0026origin).To(decorator).Build()\n\n\tfmt.Println(Foo(\"anything\"))\n\t/*\n\t\targ is anything\n\t\tres is ori:anything\n\t\tori:anything\n\t*/\n}\n```\n\n### Goroutine filtering\nBy default, mocks take effect in all goroutines. You can use the following APIs to specify in which goroutines the mock takes effect:\n- `IncludeCurrentGoRoutine`: Only takes effect in the current goroutine\n- `ExcludeCurrentGoRoutine`: Takes effect in all goroutines except the current one\n- `FilterGoRoutine`: Include or exclude specified goroutines (by goroutine id)\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc Foo(in string) string {\n\treturn in\n}\n\nfunc main() {\n\t// use `ExcludeCurrentGoRoutine` to exclude current goroutine\n\tMock(Foo).ExcludeCurrentGoRoutine().Return(\"MOCKED!\").Build()\n\tfmt.Println(Foo(\"anything\")) // anything | mock won't work in current goroutine\n\n\tgo func() {\n\t\tfmt.Println(Foo(\"anything\")) // MOCKED! | mock works in other goroutines\n\t}()\n\n\ttime.Sleep(time.Second) // wait for goroutine to finish\n\t\n\t// Tips: You can use `GetGoroutineId` to get the current goroutine ID\n}\n```\n\n### Acquire `Mocker`\nAcquire `Mocker` to use advanced features:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc Foo(in string) string {\n\treturn in\n}\n\nfunc main() {\n\tmocker := Mock(Foo).When(func(in string) bool { return len(in) \u003e 5 }).Return(\"MOCKED!\").Build()\n\tfmt.Println(Foo(\"any\"))      // any\n\tfmt.Println(Foo(\"anything\")) // MOCKED!\n\n\t// use `MockTimes` and `Times` to track the number of times mock worked and `Foo` is called\n\tfmt.Println(mocker.MockTimes()) // 1\n\tfmt.Println(mocker.Times())     // 2\n\n\t// Tips: When remocking or releasing mock, the related counters will be reset to 0.\n\n\t// remock `Foo` to return \"MOCKED2!\"\n\tmocker.Return(\"MOCKED2!\")\n\tfmt.Println(Foo(\"anything\")) // MOCKED2!\n\tfmt.Println(mocker.MockTimes()) // 1 | Reset to 0 when remocking\n\n\t// release `Foo` mock\n\tmocker.Release()\n\tfmt.Println(Foo(\"anything\")) // anything | mock won't work, because mock released\n\tfmt.Println(mocker.MockTimes()) // 0 | Reset to 0 when releasing\n}\n```\n\n## FAQ\n### How to disable inline and compile optimization?\n1. Command line：`go test -gcflags=\"all=-l -N\" -v ./...` in tests or `go build -gcflags=\"all=-l -N\"` in main packages.\n2. Goland：use Debug or fill `-gcflags=\"all=-l -N\"` in the **Run/Debug Configurations \u003e Go tool arguments** dialog box.\n3. VSCode: use Debug or add `\"go.buildFlags\": [\"-gcflags=\\'all=-N -l\\'\"]` in `settings.json`.\n\n### Mock doesn't work?\n1. Inline or compilation optimizations are not disabled. Please check if this log has been printed and refer to [relevant section](#how-to-disable-inline-and-compile-optimization) of FAQ.\n    ```\n    Mockey check failed, please add -gcflags=\"all=-N -l\".\n    ```\n2. Check if `Build()` was not called, or that neither `Return(xxx)` nor `To(xxx)` was called, resulting in no actual effect. If the target function has no return value, you still need to call the empty `Return()` or use `To` to customize the hook function.\n3. Mock targets do not match exactly, as below:\n    ```go\n    package main_test\n    \n    import (\n    \t\"fmt\"\n    \t\"testing\"\n    \n    \t. \"github.com/bytedance/mockey\"\n    )\n    \n    type A struct{}\n    \n    func (a A) Foo(in string) string { return in }\n    \n    func TestXXX(t *testing.T) {\n    \tMock((*A).Foo).Return(\"MOCKED!\").Build()\n    \tfmt.Println(A{}.Foo(\"anything\")) // won't work, because the mock target should be `A.Foo`\n    \n    \ta := A{}\n    \tMock(a.Foo).Return(\"MOCKED!\").Build()\n    \tfmt.Println(a.Foo(\"anything\")) // won't work, because the mock target should be `A.Foo`\n    }\n    ```\n   Please refer to [Generic function/method](#generic-functionmethod) if the target is generic. Otherwise, try to check if it hits specific cases in [GetMethod](#providing-getmethod-to-handle-special-cases).\n4. The target function is executed in other goroutines when mock released:\n    ```go\n    package main_test\n    \n    import (\n    \t\"fmt\"\n    \t\"testing\"\n    \t\"time\"\n    \n    \t. \"github.com/bytedance/mockey\"\n    )\n    \n    func Foo(in string) string {\n    \treturn in\n    }\n    \n    func TestXXX(t *testing.T) {\n    \tPatchConvey(\"TestXXX\", t, func() {\n    \t\tMock(Foo).Return(\"MOCKED!\").Build()\n    \t\tgo func() { fmt.Println(Foo(\"anything\")) }() // the timing of executing 'Foo' is uncertain\n    \t})\n    \t// when the main goroutine comes here, the relevant mock has been released by 'PatchConvey'. If 'Foo' is executed before this, the mock succeeds, otherwise it fails\n    \tfmt.Println(\"over\")\n    \ttime.Sleep(time.Second)\n    }\n    ```\n5. The function call happens before mock execution. Try setting a breakpoint at the first line of the original function. If the execution reaches the first line when the stack is not after the mock code in the unit test, this is the issue. Common in `init()` functions. See [relevant section](#how-to-mock-functions-in-dependency-package-init) for how to mock functions in `init()`.\n6. Using non-generic mock for generic functions. See [Generic function/method](#generic-functionmethod) section for details.\n7. Occasional mock failures or inability to restore mocks under the arm64 architecture. Please upgrade to the latest version, see [#90](https://github.com/bytedance/mockey/issues/90).\n\n### How to mock interface types?\nMethod 1: Use `GetMethod` to get the corresponding method from the instance\n```go\npackage main\n\nimport (\n   \"fmt\"\n\n   . \"github.com/bytedance/mockey\"\n)\n\ntype FooI interface {\n   Foo(string) string\n}\n\nfunc NewFoo() FooI {\n   return \u0026foo{}\n}\n\n// foo the original implementation of 'FooI'\ntype foo struct{}\n\nfunc (f *foo) Foo(in string) string {\n   return in\n}\n\nfunc main() {\n   // get the original implementation and mock it\n   instance := NewFoo()\n   Mock(GetMethod(instance, \"Foo\")).Return(\"MOCKED!\").Build()\n\n   fmt.Println(instance.Foo(\"anything\")) // MOCKED!\n}\n```\n\nMethod 2: Create a dummy implementation type and mock the corresponding constructor to return that type\n```go\npackage main\n\nimport (\n   \"fmt\"\n\n   . \"github.com/bytedance/mockey\"\n)\n\ntype FooI interface {\n   Foo(string) string\n}\n\nfunc NewFoo() FooI {\n   return \u0026foo{}\n}\n\n// foo the original implementation of 'FooI'\ntype foo struct{}\n\nfunc (f *foo) Foo(in string) string {\n   return in\n}\n\nfunc main() {\n   // generate a dummy implementation of 'FooI' and mock it\n   type foo struct{ FooI }\n   Mock((*foo).Foo).Return(\"MOCKED!\").Build()\n   // mock the constructor of 'FooI' to return the dummy implementation\n   Mock(NewFoo).Return(new(foo)).Build()\n\n   fmt.Println(NewFoo().Foo(\"anything\")) // MOCKED!\n}\n```\nMethod 3: We are working on a interface mocking feature, see [#3](https://github.com/bytedance/mockey/issues/3)\n\n### How to mock functions in dependency package init()?\nWe often encounter this problem: there is an init function in the dependency package that panics when executed in local or CI environment, causing unit tests to fail directly. We hope to mock the panicking function, but since init functions execute before unit tests, general methods cannot succeed.\n\nSuppose package a references package b, and package b's init runs a function FunC from package c. We hope to mock FunC before package a's unit test starts. Since golang's init order is dictionary order, we just need to initialize a package d with mock functions before package c's init. Here's a solution:\n\n1. Create a new package d, then create an init function in this package to mock FunC; Special attention: you need to check for CI environment (such as `os.Getenv(\"ENV\") == \"CI\"`), otherwise the production environment will also be mocked\n2. In package a's \"first go file in dictionary order\", \"additionally reference\" package d, and make package d's reference at the front of all imports\n3. Inject `ENV == \"CI\"` when running unit tests to make the mock effective\n\n## Troubleshooting\n### Error \"function is too short to patch\"？\n1. Inline or compilation optimizations are not disabled. Please check if this log has been printed and refer to [relevant section](#how-to-disable-inline-and-compile-optimization) of FAQ.\n    ```\n    Mockey check failed, please add -gcflags=\"all=-N -l\".\n    ```\n2. The function is really too short resulting in the compiled machine code is not long enough. Generally, two or more lines will not cause this problem. If there is such a need, you may use `MockUnsafe` to mock it causing unknown issues.\n3. The function has been mocked by other tools (such as [monkey](https://github.com/bouk/monkey) or [gomonkey](https://github.com/agiledragon/gomonkey) etc.)\n\n### Error \"invalid memory address or nil pointer dereference\"？\nThis is most likely an issue with your business code or test code. It is recommended to debug step by step or check for uninitialized objects. It is generally common in the following situations:\n```go\ntype Loader interface{ Foo() }\nvar loader Loader\nloader.Foo() // invalid memory address or nil pointer dereference\n```\n\n### Error \"re-mock \u003cxxx\u003e, previous mock at: xxx\"\nThe function has been mocked repeatedly in the smallest unit, as below:\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t. \"github.com/bytedance/mockey\"\n)\n\nfunc Foo() string { return \"\" }\n\nfunc main() {\n\tMock(Foo).Return(\"MOCKED!\").Build() // mock for the first time\n\tMock(Foo).Return(\"MOCKED2!\").Build() // mock for the second time, will panic!\n\tfmt.Println(Foo())\n}\n```\nFor a function, it can only be mocked once in a PatchConvey (even without PatchConvey). Please refer to [PatchConvey](#supporting-patchconvey-and-patchrun) to organize your test cases. If there is such a need, please refer to [Acquire Mocker](#acquire-mocker) to remock.\n\nIf you encounter this error when mocking the same generic function with different type arguments, it may be caused by the fact that the gcshape of different arguments is the same. For details, see the [Generic function/method](#generic-functionmethod) section.\n\n### Error \"args not match\" / \"Return Num of Func a does not match\" / \"Return value idx of rets can not convertible to\"?\n- If using `Return`, check if the return parameters are consistent with the target function's return values\n- If using `To`, check if the input and output parameters are consistent with the target function\n- If using `When`, check if the input parameters are consistent with the target function\n- If the target and hook function signatures appear identical in the error, check if the import packages in the test code and target function code are consistent\n\n### Crash \"signal SIGBUS: bus error\"?\nMac M series computers (darwin/arm64) have a higher probability of encountering this issue. You can retry multiple times. In v1.4.0, we fixed this issue (to some extent). Related discussion [here](https://github.com/bytedance/mockey/issues/68).\n```\nfatal error: unexpected signal during runtime execution\n[signal SIGBUS: bus error code=0x1 addr=0x10509aec0 pc=0x10509aec0]\n```\n\n### Crash \"signal SIGSEGV: segmentation violation\"?\nLower version MacOS (10.x / 11.x) may have the following error. Currently, you can temporarily resolve it by disabling cgo with `go env -w CGO_ENABLED=0`:\n```\nfatal error: unexpected signal during runtime execution\n[signal SIGSEGV: segmentation violation code=0x1 addr=0xb01dfacedebac1e pc=0x7fff709a070a]\n```\n\n### Crash \"semacquire not on the G stack\"?\nIt is best not to directly mock system functions as it may cause probabilistic crash issues. For example, mocking `time.Now` will cause:\n```\nfatal error: semacquire not on the G stack\n```\n\n### M series Mac + Go 1.18 goes to wrong branch?\nThis is a bug in golang under arm64 architecture for specific versions. Please check if the golang version is 1.18.1～1.18.5. If so, upgrade the golang version.\n\nGolang fix MR:\n- [go/reflect: Incorrect behavior on arm64 when using MakeFunc / Call [1.18 backport] · Issue #53397](https://github.com/golang/go/issues/53397)\n- https://go-review.googlesource.com/c/go/+/405114/2/src/cmd/compile/internal/ssa/rewriteARM64.go#28709\n\n### Error \"mappedReady and other memstats are not equal\" / \"index out of range\" / \"invalid reference to runtime.sysAlloc\"？\nThe version is too old, please upgrade to the latest version of mockey.\n\n## License\nMockey is distributed under the [Apache License](https://github.com/bytedance/mockey/blob/main/LICENSE-APACHE), version 2.0. The licenses of third party dependencies of Mockey are explained [here](https://github.com/bytedance/mockey/blob/main/licenses).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbytedance%2Fmockey","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbytedance%2Fmockey","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbytedance%2Fmockey/lists"}