Skip to content
This repository was archived by the owner on Feb 27, 2026. It is now read-only.

Repository files navigation

PkgGoDevGo Report Card

Mockc

Mockc is a completely type-safe compile-time mock generator for Go. You can use it just by writing the mock generators with mockc.Implement() or using it with command like flags.

Check out my blog post for more details.

Features

  • Tools
    • Generating mock with mock generators
    • Generating mock with command line flags (experimental feature)
  • Generated Mock
    • Capturing params and results of the method
    • Capturing method calls
    • Injecting method body
    • Customizing mock's field names with the prefix and the suffix
      • default: prefix:"_", suffix:""
    • Generating mock constructor

Installation

go get github.com/KimMachineGun/mockc/cmd/mockc

Look and Feel

You can see more examples here.

Target Interface

package basic
typeCacheinterface {
Get(keystring) (valinterface{}, errerror)
Set(keystring, valinterface{}) (errerror)
Del(keystring) (errerror)
}

If you want to generate mock that implements the above interface, follow the steps below.

With Mock Generator

1. Write Mock Generator

If you want to generate mock with mock generator, write a mock generator first. The mock will be generated in its generator path, and it'll be named its generator's name. You can write multiple generators in one file, and multiple mocks will be generated. The mock generator should be consisted of function calls of the mockc package.

//+build mockcpackage basic
import (
"github.com/KimMachineGun/mockc"
)
funcMockcCache() {
mockc.Implement(Cache(nil))
}

If you want to customize the field names of the mock, use mockc.SetFieldNamePrefix() or mockc.SetFieldNameSuffix(). (Notice: These functions only work with constant string value.)

2. Generate Mock

This command will generate mock with your mock generator. The <package-pattern> argument will be used for loading mock generator with golang.org/x/tools/go/packages#Load. If it's not provided, . will be used.

mockc [<packages-pattern>]
Ex: mock ./example

With Command Line Flags

1. Generate Mock

This command will generate mock with its command line flags. If you generate mock with this command, you don't need to write the mock generator. The <target-interface-pattern> should follow {package_path}.{interface_name} format.

mockc -destination=<output-file> -name=<mock-name> [-withConstructor] [-fieldNamePrefix=<prefix>] [-fieldNameSuffix=<suffix>] <target-interface-pattern> [<target-interface-pattern>]
Ex: mockc -destination=./example/mockc_gen.go -name=MockcCache github.com/KimMachineGun/mockc/example.Cache

If you want to customize the field names of the mock, pass string value to the -fieldNamePrefix or -fieldNameSuffix.

Generated Mock

The //go:generate directive may vary depending on your mock generation command.

// Code generated by Mockc. DO NOT EDIT.// repo: https://github.com/KimMachineGun/mockc//go:generate mockc// +build !mockcpackage basic
import"sync"var_interface {
Cache
} =&MockcCache{}
typeMockcCachestruct {
// method: Del_Delstruct {
mu sync.Mutex// basicsCalledboolCallCountint// call historyHistory []struct {
Paramsstruct {
P0string
}
Resultsstruct {
R0error
}
}
// paramsParamsstruct {
P0string
}
// resultsResultsstruct {
R0error
}
// if it is not nil, it'll be called in the middle of the method.Bodyfunc(string) error
}
// method: Get_Getstruct {
mu sync.Mutex// basicsCalledboolCallCountint// call historyHistory []struct {
Paramsstruct {
P0string
}
Resultsstruct {
R0interface{}
R1error
}
}
// paramsParamsstruct {
P0string
}
// resultsResultsstruct {
R0interface{}
R1error
}
// if it is not nil, it'll be called in the middle of the method.Bodyfunc(string) (interface{}, error)
}
// method: Set_Setstruct {
mu sync.Mutex// basicsCalledboolCallCountint// call historyHistory []struct {
Paramsstruct {
P0stringP1interface{}
}
Resultsstruct {
R0error
}
}
// paramsParamsstruct {
P0stringP1interface{}
}
// resultsResultsstruct {
R0error
}
// if it is not nil, it'll be called in the middle of the method.Bodyfunc(string, interface{}) error
}
}
func (recv*MockcCache) Del(p0string) error {
recv._Del.mu.Lock()
deferrecv._Del.mu.Unlock()
// basicsrecv._Del.Called=truerecv._Del.CallCount++// paramsrecv._Del.Params.P0=p0// bodyifrecv._Del.Body!=nil {
recv._Del.Results.R0=recv._Del.Body(p0)
}
// call historyrecv._Del.History=append(recv._Del.History, struct {
Paramsstruct {
P0string
}
Resultsstruct {
R0error
}
}{
Params: recv._Del.Params,
Results: recv._Del.Results,
})
// resultsreturnrecv._Del.Results.R0
}
func (recv*MockcCache) Get(p0string) (interface{}, error) {
recv._Get.mu.Lock()
deferrecv._Get.mu.Unlock()
// basicsrecv._Get.Called=truerecv._Get.CallCount++// paramsrecv._Get.Params.P0=p0// bodyifrecv._Get.Body!=nil {
recv._Get.Results.R0, recv._Get.Results.R1=recv._Get.Body(p0)
}
// call historyrecv._Get.History=append(recv._Get.History, struct {
Paramsstruct {
P0string
}
Resultsstruct {
R0interface{}
R1error
}
}{
Params: recv._Get.Params,
Results: recv._Get.Results,
})
// resultsreturnrecv._Get.Results.R0, recv._Get.Results.R1
}
func (recv*MockcCache) Set(p0string, p1interface{}) error {
recv._Set.mu.Lock()
deferrecv._Set.mu.Unlock()
// basicsrecv._Set.Called=truerecv._Set.CallCount++// paramsrecv._Set.Params.P0=p0recv._Set.Params.P1=p1// bodyifrecv._Set.Body!=nil {
recv._Set.Results.R0=recv._Set.Body(p0, p1)
}
// call historyrecv._Set.History=append(recv._Set.History, struct {
Paramsstruct {
P0stringP1interface{}
}
Resultsstruct {
R0error
}
}{
Params: recv._Set.Params,
Results: recv._Set.Results,
})
// resultsreturnrecv._Set.Results.R0
}

Feel Free to Use the Generated Mock

package basic
import (
"errors""testing"
)
funcHasKey(cCache, keystring) (bool, error) {
val, err:=c.Get(key)
iferr!=nil {
returnfalse, err
}
returnval!=nil, nil
}
funcTestHasKey(t*testing.T) {
m:=&MockcCache{}
// set return valuem._Get.Results.R0=struct{}{}
// executekey:="test_key"result, err:=HasKey(m, key)
// assertif!result {
t.Error("result should be true")
}
iferr!=nil {
t.Error("err should be nil")
}
ifm._Get.CallCount!=1 {
t.Errorf("Cache.Get should be called once: actual(%d)", m._Get.CallCount)
}
ifm._Get.Params.P0!=key {
t.Errorf("Cache.Get should be called with %q: actual(%q)", key, m._Get.Params.P0)
}
}
funcTestHasKey_WithBodyInjection(t*testing.T) {
m:=&MockcCache{}
// inject bodykey:="test_key"m._Get.Body=func(actualKeystring) (interface{}, error) {
ifactualKey!=key {
t.Errorf("Cache.Get should be called with %q: actual(%q)", key, actualKey)
}
returnnil, errors.New("error")
}
// executeresult, err:=HasKey(m, key)
// assertifresult {
t.Error("result should be false")
}
iferr==nil {
t.Error("err should not be nil")
}
ifm._Get.CallCount!=1 {
t.Errorf("Cache.Get should be called once: actual(%d)", m._Get.CallCount)
}
}

Inspired by 🙏

About

Completely type-safe compile-time mock generator for Go

Topics

Resources

Stars

33 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages