{"id":24432254,"url":"https://github.com/bayer-group/mocka","last_synced_at":"2025-04-12T13:37:09.205Z","repository":{"id":40543558,"uuid":"194739164","full_name":"Bayer-Group/mocka","owner":"Bayer-Group","description":"Mocka is a mocking and stubbing package written for the Go programming language.","archived":false,"fork":false,"pushed_at":"2022-05-03T14:41:17.000Z","size":197,"stargazers_count":9,"open_issues_count":4,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-26T08:11:47.781Z","etag":null,"topics":["golang","golang-package","mocking","stubbing","testing"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/MonsantoCo/mocka","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Bayer-Group.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-01T20:33:44.000Z","updated_at":"2024-02-01T22:55:46.000Z","dependencies_parsed_at":"2022-07-23T14:46:21.063Z","dependency_job_id":null,"html_url":"https://github.com/Bayer-Group/mocka","commit_stats":null,"previous_names":["monsantoco/mocka"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bayer-Group%2Fmocka","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bayer-Group%2Fmocka/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bayer-Group%2Fmocka/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Bayer-Group%2Fmocka/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Bayer-Group","download_url":"https://codeload.github.com/Bayer-Group/mocka/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248574098,"owners_count":21126953,"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","golang-package","mocking","stubbing","testing"],"created_at":"2025-01-20T15:36:24.856Z","updated_at":"2025-04-12T13:37:09.185Z","avatar_url":"https://github.com/Bayer-Group.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mocka [![Build Status][build-badge]][build-ci] [![gopherbadger-tag-do-not-edit][coverage-badge]][coverage] [![GoDoc][godoc-badge]][godoc]\n\n```go\nimport \"github.com/Bayer-Group/mocka/v2\"\n```\n\nMocka is a simple mocking and stubbing library for the [Go programming language][golang]. It is used to assist with writing unit tests around third-party functions.\n\nAll changes will be reflected in the [CHANGELOG][changelog].\n\n\u003e If you are looking to migrate from **v1** to **v2** check out the [migration guide][migrationGuide].\n\n## Why Mocka?\n\nThere are times when you would want to control the output of a third-party function in testing. Sometimes making a wrapper around that package/function is more effort than it is worth. Mocka is here to solve that problem. It allows you to control the output of functions without needing to write any additional code. \n\nCurrently if you would want to control the output of a function in go it would be akin to\n\n```go\n// --- main.go ---\n\n// alias function for unit testing\nvar jsonMarshal = json.Marshal\n\n...\n\n// --- main_test.go ---\n\n// create temporary variable to store original function\nvar jsonMarshalOriginal func(v interface{}) ([]byte, error)\n\nfunc TestMarshal(t *testing.T) {\n    jsonMarshalOriginal = jsonMarshal\n    jsonMarshal = func(v interface{}) ([]byte, error) {\n        return []byte(\"value\"), nil\n    }\n    defer func() {\n        jsonMarshal = jsonMarshalOriginal\n    }()\n    \n    // Your test code\n}\n```\n\nThis structure increases the length of unit tests; depending on how many functions are needing to control. Mocka provides a safe way to stub functions while also reducing the amount of code required.\n\n\u003e Mocka does this safely using reflection, no calls to the `unsafe` package are made.\n\nThe mocka way would be\n\n```go\n// --- main.go ---\n\n// alias function for unit testing (in production code)\nvar jsonMarshal = json.Marshal\n\n...\n\n// --- main_test.go ---\n\nfunc TestMarshal(t *testing.T) {\n    stub := mocka.Function(t, \u0026jsonMarshal, []byte(\"value\"), nil)\n    defer stub.Restore()\n    \n    // Your test code\n}\n```\n\n\u003e The `encoding/json` package was used in examples for simplicity and not for the need to control it's output. \n\n## Test Reporter\n\nThere are some cases when interacting with a stub where errors can occur. Mocka uses a custom interface called `TestReporter`, which is defined below, to fail tests for you.\n\n```go\ntype TestReporter interface {\n    Errorf(string, ...interface{})\n}\n```\n\n`TestReporter` is satisfied by the built-in `testing.T` and other testing frameworks like [Ginkgo][ginkgo] by using `GinkgoT()`. \n\n## Stubs\n\n### Creating a Stub\n\n```go\nfunc Function(\n    testReporter TestReporter,\n    functionPointer interface{},\n    returnValues ...interface{}) *Stub {\n        \n    }\n```\n\n`mocka.Function` replaces the provided function with a stubbed implementation. The `Stub` has the ability to change the return values of the original function in many different cases. It also provides the ability to get metadata associated to any call against the original function.\n\n### Restoring a function's original functionality\n\nAfter creating a `Stub` it is recommended to `defer` it's restoration. This is to ensure that the `Stub` returns the original functionality back to the function. To restore a `Stub` call the `Restore` function.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str string) int {\n        return len(str)\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    defer stub.Restore()\n\n    actual := fn(\"1\")\n    if actual != 20 {\n        t.Errorf(\"expected 20 but got %v\", actual)\n    }\n}\n```\n\n\u003c/details\u003e\n\n### Changing the return values of a Stub\n\nMocka allows for the return values of a `Stub` to be changed at any time and in many different cases. When creating `Stub` it is required to specify a default set of return values it will return. If you want to change the default return values after the stub has been created simply call `Return` on the `Stub`.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str string) int {\n        return len(str)\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    defer stub.Restore()\n\n    if actual := fn(\"123\"); actual != 20 {\n        t.Errorf(\"expected 20 but got %v\", actual)\n    }\n\n    stub.Return(5)\n\n    if actual := fn(\"123\"); actual != 5 {\n        t.Errorf(\"expected 5 but got %v\", actual)\n    }\n}\n```\n\n\u003c/details\u003e\n\n### Changing the return values of a stub based on the call index\n\nMocka allows for return values to be changed based on how many times the original function has been called. To change the return values use the `OnCall` method that can be used by either the `Stub` or a custom set of arguments.\n\n\u003e The _callIndex_ uses zero-based indexing.\n\nMocka provides helper functions for accessing the first three times a function has been called. Instead of using the `OnCall` method the following methods can be used `OnFirstCall`, `OnSecondCall`, or `OnThirdCall`.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str string) int {\n        return len(str)\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    defer stub.Restore()\n\n    withArgs123 := stub.WithArgs(\"123\")\n\n    withArgs123.OnCall(1).Return(5)\n    withArgs123.OnCall(3).Return(3)\n    \n    if actual := fn(\"123\"); actual != 20 {\n        t.Errorf(\"expected 20 but got %v\", actual)\n    }\n    \n    if actual := fn(\"123\"); actual != 5 {\n        t.Errorf(\"expected 5 but got %v\", actual)\n    }\n    \n    if actual := fn(\"123\"); actual != 20 {\n        t.Errorf(\"expected 20 but got %v\", actual)\n    }\n    \n    if actual := fn(\"123\"); actual != 3 {\n        t.Errorf(\"expected 3 but got %v\", actual)\n    }\n}\n```\n\n\u003c/details\u003e\n\n### Changing the return values of a Stub based on the arguments\n\nMocka allows for return values to be changed based on the arguments provided to the function. This can be done by using the `WithArgs` method on the `Stub`.\n\n\u003e If `Return` is not called on the `OnCallReturner` interface then it be ignored until `Return` is called.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str []string, n int) int {\n        return len(str) + n\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    defer stub.Restore()\n\n    stub.WithArgs([]string{\"123\", \"456\"}, 2).Return(5)\n\n    fmt.Println(fn([]string{\"123\", \"456\"}, 2))\n\n    if actual := fn([]string{\"123\", \"456\"}, 2); actual != 5 {\n        t.Errorf(\"expected 5 but got %v\", actual)\n    }\n}\n```\n\n\u003c/details\u003e\n\n#### Changing the return values for a Stub based on variadic arguments\n\nmocka accepts variadic arguments for `WithArgs` the same as if you were calling the function itself.\n\n\u003e You can still pass in custom matchers from the `match` package for each element in the variadic list.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str string, opts ...string) int {\n        return len(str) + len(opts)\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    stub.WithArgs(\"A\", \"B\", \"C\").Return(5)\n\n    if actual := fn(\"A\", \"B\", \"C\"); actual != 5 {\n        t.Errorf(\"expected 5 but got %v\", actual)\n    }\n    \n    if actual := fn(\"A\"); actual != 20 {\n        t.Errorf(\"expected 20 but got %v\", actual)\n    }\n}\n```\n\n\u003c/details\u003e\n\n#### Changing the return values for a Stub based on the call index of specific arguments\n\nSimilar to the `Stub` the return values can be changed based on the call index of the original function for a specifc set of arguments. To change the return values for a specific call index use the `OnCall` method.\n\nmocka provides helper functions for accessing the first three times a function has been called. Instead of using the `OnCall` method the following methods can be used `OnFirstCall`, `OnSecondCall`, or `OnThirdCall`.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str string) int {\n        return len(str)\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    defer stub.Restore()\n\n    withArgs123 := stub.WithArgs(\"123\")\n\n    withArgs123.OnCall(1).Return(5)\n    withArgs123.OnCall(3).Return(3)\n    \n    if actual := fn(\"123\"); actual != 20 {\n        t.Errorf(\"expected 20 but got %v\", actual)\n    }\n    \n    if actual := fn(\"123\"); actual != 5 {\n        t.Errorf(\"expected 5 but got %v\", actual)\n    }\n    \n    if actual := fn(\"123\"); actual != 20 {\n        t.Errorf(\"expected 20 but got %v\", actual)\n    }\n    \n    if actual := fn(\"123\"); actual != 3 {\n        t.Errorf(\"expected 3 but got %v\", actual)\n    }\n}\n```\n\n\u003c/details\u003e\n\n#### Changing the return values for a Stub based on argument matchers\n\nmocka provides a powerful `match` package that can be used in conjunction with the `WithArgs` function. Sometimes you might not know the exact value a function is called with. This is a scenario where matchers can help navigate around that problem.\n\nCurrently there are over 25 built in matchers you can use. More information can be found at [matcher descriptions](./MATCH.md).\n\n\u003e The `match` package also provides the ability to create your own custom matchers.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str []string, n int) int {\n        return len(str) + n\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    defer stub.Restore()\n\n    stub.WithArgs(match.Anything(), 2).Return(10)\n    stub.WithArgs([]string{\"123\", \"456\"}, 2).Return(5)\n\n    if actual := fn([]string{\"hello\"}, 5); actual != 20 {\n        t.Errorf(\"expected 20 but got %v\", actual)\n    }\n    \n    if actual := fn([]string{\"mocka\"}, 2); actual != 10 {\n        t.Errorf(\"expected 10 but got %v\", actual)\n    }\n    \n    if actual := fn([]string{\"123\", \"456\"}, 2); actual != 5 {\n        t.Errorf(\"expected 5 but got %v\", actual)\n    }\n}\n```\n\n\u003c/details\u003e\n\n### Retrieving the arguments and return values from a Stub\n\nSetting the return values is only half of what mocka can do. Once a `Stub` has been called you can retrieve the arguments and return values the original function was called with.\n\n#### Retrieve how many times the function was called\n\nYou can get how many times the original function was called after stubbing the function by using `CallCount`.\n\nmocka provides helper functions for checking if a `Stub` has been called at least the first three times. Instead of using the `CallCount` method the following methods can be used `CalledOnce`, `CalledTwice`, or `CalledThrice`.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str string) int {\n        return len(str)\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    defer stub.Restore()\n\n    fn(\"first call\")\n    fn(\"second call\")\n    fn(\"third call\")\n\n    if actual := stub.CallCount(); actual != 3 {\n        t.Errorf(\"expected 3 but got %v\", actual)\n    }\n}\n```\n\n\u003c/details\u003e\n\n#### Retrieve the arguments and return values for all calls against the original function\n\n`GetCalls` returns all calls made to the original function that where captured by the stubbed implementation.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\ntype test struct {\n    arguments []interface{}\n    returnValues []interface{}\n}\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str string) int {\n        return len(str)\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    defer stub.Restore()\n\n    fn(\"first call\")\n    fn(\"second call\")\n    fn(\"third call\")\n\n    calls := stub.GetCalls()\n    if len(calls) != 3 {\n        t.Fatalf(\"expected 3 but got %v\", actual)\n    }\n    \n    tests := []test{\n        {arguments: []interface{}{\"first call\"}, returnValues: []interface{}{20}},\n        {arguments: []interface{}{\"second call\"}, returnValues: []interface{}{20}},\n        {arguments: []interface{}{\"third call\"}, returnValues: []interface{}{20}},\n    }\n    \n    for i, tc := range tests {\n        call := calls[i]\n        if !reflect.DeepEqual(tc.arguments, call.Arguments()) {\n            t.Fatalf(\"expected arguments: %v, got: %v\", tc.arguments, call.Arguments())\n        }\n        \n        if !reflect.DeepEqual(tc.returnValues, call.ReturnValues()) {\n            t.Fatalf(\"expected return values: %v, got: %v\", tc.returnValues, call.ReturnValues())\n        }\n    }\n}\n```\n\n\u003c/details\u003e\n\n#### Retrieve the arguments and return values for a specific call to the original function\n\n`GetCall` returns the arguments and return values of the original function that was captured by the stubbed implementation. It will return these values for the specified time the function was called.\n\n`GetCall` will also panic if the call index is lower than zero or greater than the number of times the function was called.\n\n\u003e The call index uses zero-based indexing\n\nmocka provides helper functions for retrieving the arguments and return values for the first three calls. Instead of using the `GetCall` method the following methods can be used `GetFirstCall`, `GetSecondCall`, or `GetThirdCall`.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(str string) int {\n        return len(str)\n    }\n\n    stub := mocka.Function(t, \u0026fn, 20)\n    defer stub.Restore()\n\n    fn(\"first call\")\n    fn(\"second call\")\n    fn(\"third call\")\n\n    call := stub.GetCall(2)\n    if !reflect.DeepEqual([]interface{}{\"third call\"}, call.Arguments()) {\n        t.Fatalf(\"expected arguments: %v, got: %v\", []interface{}{\"third call\"}, call.Arguments())\n    }\n    \n    if !reflect.DeepEqual([]interface{}{20}, call.ReturnValues()) {\n        t.Fatalf(\"expected return values: %v, got: %v\", []interface{}{20}, call.ReturnValues())\n    }\n}\n```\n\n\u003c/details\u003e\n\n\n### Executing a function when a stub is called\n\nIn some special cases code will need to be run when the original function is called. This code is usually for performing side-effects. Mocka provides the ability to give a `Stub` a function to be called when the original function is called. Call `ExecOnCall` providing a function with the following signature `func(arguments []interface{}) {}` to have it be called when the original function is called. This function will be called with the same arguments the original function is called with.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestMocka(t *testing.T) {\n    fn := func(in \u003c-chan int) \u003c-chan int {\n        out := make(chan int, 1)\n        go func() {\n            out \u003c- \u003c-in\n        }()\n        return out\n    }\n\n    out := make(chan int, 1)\n    stub := mocka.Function(t, \u0026fn, out)\n    defer stub.Restore()\n\n    stub.ExecOnCall(func(args []interface{}) {\n        c := args[0].(\u003c-chan int)\n        out \u003c- \u003c-c\n    })\n\n    in := make(chan int, 1)\n    in \u003c- 10\n    if actual := \u003c-fn(in); actual != 10 {\n        t.Fatalf(\"expected: 10 got: %v\", actual)\n    }\n}\n```\n\n\u003c/details\u003e\n\n## Sandboxes\n\nIn many cases you might need to stub out many functions in a single test file. A `Sandbox` allows you to simplify the restoration of many stubbed functions. You can create one `Sandbox` where you can only call `.Restore()` once for all stubbed functions. \n\nTo create a `Sandbox` call `mocka.CreateSandbox` passing in a [test reporter](#test-reporter). The test reporter will be used to fail any tests where a stubbing error occurs. All stubs created from the `Sandbox` will use the same test reporter.\n\n### API\n\n### Creating a `Sandbox`\n\n```go\nfunc Function(functionPointer interface{}, returnValues ...interface{}) {}\n```\n\n`Sandbox.Function` behaves the same as `mocka.Function`. It replaces the provided function with a stubbed implementation. The stub has the ability to change change the return values of the original function in many different cases. The stub also provides the ability to get metadata associated to any call against the original function.\n\n### Restoring a `Sandbox`\n\n```go\nfunc Sandbox.Restore() {}\n```\n\n`Sandbox.Restore` will call `.Restore()` on all stubs that have been created from the sandbox. Once the stubs have been restored they are removed from the sandbox. To ensure no other tests are effected by the stubs created from a `Sandbox`, restore it after every test. \n\nIt is recommended to call `Sandbox.Restore` in a _defer_ directly after the sandboxes creation. If you are using a different testing package like [Ginkgo][ginkgo] then placing the restoration call in the `AfterEach(func())` will work as well.\n\n\n\u003cdetails\u003e\n\u003csummary\u003eExample\u003c/summary\u003e\n\n```go\npackage main\n\nimport (\n    \"testing\"\n\n    \"github.com/Bayer-Group/mocka/v2\"\n)\n\nfunc TestSandbox(t *testing.T) {\n    fn := func(str string) int {\n        return len(str)\n    }\n\n    sandbox := mocka.CreateSandbox(t)\n    defer sandbox.Restore()\n\n    sandbox.Function(\u0026fn, 20)\n\n    actual := fn(\"1\")\n    if actual != 20 {\n        t.Errorf(\"expected 20 but got %v\", actual)\n    }\n}\n```\n\u003c/details\u003e\n\n[changelog]: https://github.com/Bayer-Group/mocka/blob/master/CHANGELOG.md\n[coverage]: https://github.com/jpoles1/gopherbadger\n[coverage-badge]: https://img.shields.io/badge/Go%20Coverage-100%25-brightgreen.svg?longCache=true\u0026style=flat\n[golang]:          http://golang.org/\n[golang-install]:  http://golang.org/doc/install.html#releases\n[build-badge]: https://github.com/Bayer-Group/mocka/workflows/build/badge.svg\n[build-ci]:       https://github.com/Bayer-Group/mocka/actions?query=workflow%3A%22build%22\n[godoc-badge]:     https://godoc.org/github.com/Bayer-Group/mocka/?status.svg\n[godoc]:           https://pkg.go.dev/github.com/Bayer-Group/mocka/v2?tab=doc\n[ginkgo]: https://github.com/onsi/ginkgo\n[migrationGuide]: https://github.com/Bayer-Group/mocka/blob/master/MIGRATE_TO_V2.md\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbayer-group%2Fmocka","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbayer-group%2Fmocka","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbayer-group%2Fmocka/lists"}