Interface mocking tool for go generate

moq logo build Go Report Card

Interface mocking tool for go generate.

What is Moq?

Moq is a tool that generates a struct from any interface. The struct can be used in test code as a mock of the interface.

Preview

above: Moq generates the code on the right.

You can read more in the Meet Moq blog post.

Installing

To start using latest released version of Moq, just run:

Go version < 1.16

$ go get github.com/matryer/moq

Go 1.16+

$ go install github.com/matryer/moq@latest

Usage

moq [flags] source-dir interface [interface2 [interface3 [...]]]
	-fmt string
		go pretty-printer: gofmt, goimports or noop (default gofmt)
	-out string
		output file (default stdout)
	-pkg string
		package name (default will infer)
	-stub
		return zero values when no mock implementation is provided, do not panic
	-skip-ensure
		suppress mock implementation check, avoid import cycle if mocks
		generated outside of the tested package

Specifying an alias for the mock is also supported with the format 'interface:alias'

Example: moq -pkg different . MyInterface:MyMock

NOTE: source-dir is the directory where the source code (definition) of the target interface is located. It needs to be a path to a directory and not the import statement for a Go package.

In a command line:

$ moq -out mocks_test.go . MyInterface

In code (for go generate):

package my

//go:generate moq -out myinterface_moq_test.go . MyInterface

type MyInterface interface {
	Method1() error
	Method2(i int)
}

Then run go generate for your package.

How to use it

Mocking interfaces is a nice way to write unit tests where you can easily control the behaviour of the mocked object.

Moq creates a struct that has a function field for each method, which you can declare in your test code.

In this example, Moq generated the EmailSenderMock type:

func TestCompleteSignup(t *testing.T) {

	var sentTo string

	mockedEmailSender = &EmailSenderMock{
		SendFunc: func(to, subject, body string) error {
			sentTo = to
			return nil
		},
	}

	CompleteSignUp("[email protected]", mockedEmailSender)

	callsToSend := len(mockedEmailSender.SendCalls())
	if callsToSend != 1 {
		t.Errorf("Send was called %d times", callsToSend)
	}
	if sentTo != "[email protected]" {
		t.Errorf("unexpected recipient: %s", sentTo)
	}

}

func CompleteSignUp(to string, sender EmailSender) {
	// TODO: this
}

The mocked structure implements the interface, where each method calls the associated function field.

Tips

  • Keep mocked logic inside the test that is using it
  • Only mock the fields you need
  • It will panic if a nil function gets called
  • Name arguments in the interface for a better experience
  • Use closured variables inside your test function to capture details about the calls to the methods
  • Use .MethodCalls() to track the calls
  • Use go:generate to invoke the moq command
  • If Moq fails with a go/format error, it indicates the generated code was not valid. You can run the same command with -fmt noop to print the generated source code without attempting to format it. This can aid in debugging the root cause.

License

The Moq project (and all code) is licensed under the MIT License.

Moq was created by Mat Ryer and David Hernandez, with ideas lovingly stolen from Ernesto Jimenez. Featuring a major refactor by @sudo-suhas, as well as lots of other contributors.

The Moq logo was created by Chris Ryer and is licensed under the Creative Commons Attribution 3.0 License.

Owner
Mat Ryer
Engineering director at @Grafana - Gopher, developer, speaker, author (Go Programming Blueprints) - Xbar (BitBar reboot) xbarapp.com (now in beta)
Mat Ryer
Comments
  • Imports of vendored packages add the vendor prefix to the import path

    Imports of vendored packages add the vendor prefix to the import path

    I recently updated moq (imports, yay!) and tried regenerating one of my files and got the following imports generated:

    package mocks
    
    // AUTOGENERATED BY MOQ
    // github.com/matryer/moq
    
    import (
    	"sync"
    	"<myrepo>/vendor/golang.org/x/net/context"
    )
    

    This obviously doesn't work.

  • Internal registry for disambiguated imports, vars

    Internal registry for disambiguated imports, vars

    - Move functionality in the moq package partially into 
      internal/{registry,template}.
    - Leverage registry to assign unique package and variable/method
      parameter names. Use import aliases if present in interface source
      package.
    
    BREAKING CHANGE: When the interface definition does not mention the 
    parameter names, the field names in call info anonymous struct will be
    different. 
    
    The new field names are generated using the type info (string -> s, 
    int -> n, chan int -> intCh, []MyType -> myTypes, map[string]int ->
    stringToInt etc.).
    
    For example, for a string parameter previously if the field name was 
    'In1', the new field could be 'S' or 'S1' (depends on number of
    string method parameters).
    

    Closes #68, #94 Replaces and closes #63, #120, #121, #127

    TODO:

    • [x] Add tests
    • [x] Godocs

    @matryer this is a significant refactor and would be very good to get a review.

    edit: Presentation deck - https://docs.google.com/presentation/d/1-HVOygCVpQQ_8ikE2_OYzlvuH1NYI3wT02PWn0Onpcc/edit?usp=sharing, which

    • enumerates the problems that this PR tries to solve
    • compares with existing PRs
    • walks through the changes being done in this PR.
  • -fmt command to specify formats `gofmt` or `goimports`

    -fmt command to specify formats `gofmt` or `goimports`

    More a request for improvement than a bug report.

    Request:

    After generating the moq files, run them through gofmt.

    Use case:

    When manually changing a generated file, saving it causes gofmt to run, leading to a bigger diff in version control. I know that I could a) simply avoid changing the file manually and instead re-generate it or b) perform the changes in an editor that does not automatically run gofmt, or c) add a pre-commit hook to run gofmt on all .go files.
    It would be nice to have nonetheless and solve a minor pain point for me :)

  • Handle import name collisions

    Handle import name collisions

    I fixed these issue before I looked to see if an existing PR was in the works, but I thought I'd submit this anyways. This should supercede #120 and #121.

    Three cases are handled

    1. We maintain aliases from the source files. This is just a nicety and not really needed. This just makes the code prettier that is generated.
    2. Imports that conflict from multiple source files are handled.
    3. If the source file package conflict with an import. For example
    package foo
    
    import "foo"
    
    type Example interface {
        Bad() foo.Bar
    }
    

    Using -pkg bar you would get a conflict on foo.Bar and foo.Example

    Fixes #68 Fixes #94

  • Resolve name shadowing between imports and params

    Resolve name shadowing between imports and params

    If the interface to be mocked requires an import that is shadowed by a param with the same name, it's unlikely to be a problem for the upstream interface (and thus go undetected), but it causes moq to generate invalid code.

    Example in the wild: https://github.com/kubernetes/helm/blob/534193640179fe3c9ffc3012a7bc4e8b23fbe832/pkg/helm/interface.go#L28 (the conflict is between the chart param and the chart import)

  • -stub flag

    -stub flag

    Added a -stub flag that removes the panic behavior if an unset call is made. With this flag, unset methods return zero values instead. For the function signature:

    Four(string, bool, int) (string, error)
    

    The generated code without -stub (ie. with the current version of Moq) is:

    // Four calls FourFunc.
    func (mock *MyInterfaceMock) Four(in1 string, in2 bool, in3 int) (string, error) {
    	if mock.FourFunc == nil {
    		panic("moq: MyInterfaceMock.FourFunc is nil but MyInterface.Four was just called")
    	}
    	callInfo := struct {
    		In1 string
    		In2 bool
    		In3 int
    	}{
    		In1: in1,
    		In2: in2,
    		In3: in3,
    	}
    	lockMyInterfaceMockFour.Lock()
    	mock.calls.Four = append(mock.calls.Four, callInfo)
    	lockMyInterfaceMockFour.Unlock()
    	return mock.FourFunc(in1, in2, in3)
    }
    

    With the -stub flag in this PR, the generated code is:

    // Four calls FourFunc.
    func (mock *MyInterfaceMock) Four(in1 string, in2 bool, in3 int) (_r0 string, _r1 error) {
    	if mock.FourFunc != nil {
    		callInfo := struct {
    			In1 string
    			In2 bool
    			In3 int
    		}{
    			In1: in1,
    			In2: in2,
    			In3: in3,
    		}
    		lockMyInterfaceMockFour.Lock()
    		mock.calls.Four = append(mock.calls.Four, callInfo)
    		lockMyInterfaceMockFour.Unlock()
    		_r0, _r1 = mock.FourFunc(in1, in2, in3)
    	}
    	return
    }
    

    The -stub generate code will return the default zero values for all return types if the function field in the mock struct is unset, rather than panicking. This is defined as a command line flag (that is off by default) to avoid changing the generator's behavior for existing user. Fixes #36.

    Note to reviewers: I made a duplicate of the template variable to avoid cluttering the existing template. The only lines that I changed in the duplicated template string are line numbers 157-178 in the diff. All other lines are identical to the existing template string.

  • fix cyclic dependency with go modules

    fix cyclic dependency with go modules

    Previous code couldn't load correct package path outside gopath. packagePath := stripGopath(filepath.Join(wd, src, packageName)) was returning a full directory name and packageQualifier wasn't able to detect the same package path. Now all the packages are loading with go/packages.

    Also added a couple of tests for go modules.

    Fixes #92

  • Allow aliasing interface name

    Allow aliasing interface name

    Implementation based on #57. ~~Additionally, handle the destination pkg having 'mock' in its name.~~ - not necessary, the user can define the alias as per their requirement.

    TODO: Update README(need some tips)

    Closes #57 Closes #106 Closes #67

  • rm flag

    rm flag

    This PR adds a -rm flag, that allows for the target mock file to be removed (if it already exists).

    Mock generation occasionally fails. But when the target mock file is removed and moq is run again, the generation succeeds.

    This has happened for me and my colleagues, across multiple projects at multiple companies. Sorry I haven't got an examples at hand 😄

  • -stub flag

    -stub flag

    • Added a -stub flag that removes the panic behavior if an unset call is made.
    • With this flag, unset methods return zero values instead.
    • Updated tests for altered moq.New() function signature.
    • Changed "destination" var and in usage to "source", to reflect its actual functionality (fixes matryer/moq#85).

    Per request, rebased #46 against master. Also integrated a quick fix for #85.

  • Package name redeclared when shadowing packages and using pkg flag

    Package name redeclared when shadowing packages and using pkg flag

    This probably doesn't affect many people, and it isn't super important, but let's say you create a package with a name that is the same as a package it uses. Eg I might make github.com/xxx/myapp/http and inside of it use the net/http package.

    package http
    
    //go:generate moq -pkg http_test -out thing_moq_test.go . Thing
    
    type Thing interface {
      Blah(w http.ResponseWriter, r *http.Request)
    }
    

    If I do this AND use the -pkg flag, the following is generated:

    import (
      "github.com/xxx/myapp/http"
      "net/http"
      "sync"
    )
    

    And this doesn't work 😢

    This isn't urgent at all as I can just NOT use the -pkg flag and make it work. I'm just pointing it out because I ran into it today.

  • API for argument-based assertions

    API for argument-based assertions

    The only reason why I use gomock instead of this is that I can't simply do stuff like

    v.EXPECT(1).RETURN(2)
    v.EXPECT(2).RETURN(2)
    v.EXPECT(3).RETURN(2)
    

    I mean I have to write some if statements and so on. Looks like there's no easy way to configure several calls of mock. It looks especially complicated in a go-way-ish table-driven-tests

  • Is there a way to speed up the moq generation time?

    Is there a way to speed up the moq generation time?

    Hi!

    Just wondering is there a way to speed up the moq generation time? Something like gomockhandler for mockgen, or committing the generated files and ensure that they kept up-to-date.

    Currently in our project, running go generate ./... takes around 3-4 minutes, we have 68 instances of //go:generate moq in our codebase.

    Thanks.

  • Moq ignores package names of arguments of generic types

    Moq ignores package names of arguments of generic types

    When mocking a method with a generic type, moq ignores package names of type arguments.

    This works:

    package example
    
    //go:generate moq -skip-ensure -stub -rm -out mocks.go . Foo:FooMock
    
    type Bar[T any] struct{}
    
    type Foo interface {
    	Foo(bar Bar[Type])
    }
    

    But this does not:

    package example
    
    //go:generate moq -skip-ensure -stub -rm -out mocks.go . Foo:FooMock
    
    import "path/to/pkg"
    
    type Bar[T any] struct{}
    
    type Foo interface {
    	Foo(bar Bar[pkg.Type])
    }
    

    The generated code instantiates Bar as Bar[Type] instead of Bar[pkg.Type], failing to compile:

    // Code generated by moq; DO NOT EDIT.
    // github.com/matryer/moq
    
    package example
    
    import (
    	"sync"
    )
    
    type FooMock struct {
    	// FooFunc mocks the Foo method.
    	FooFunc func(bar Bar[Type])
    
    	// calls tracks calls to the methods.
    	calls struct {
    		// Foo holds details about calls to the Foo method.
    		Foo []struct {
    			// Bar is the bar argument value.
    			Bar Bar[Type]
    		}
    	}
    	lockFoo sync.RWMutex
    }
    

    I've tried workarounds like dot imports and type aliases, but got the same results. If Bar type is a built-in like map, it works fine. moq version v0.2.7.

  • Error on M1 Mac when generating mocks with confluent-kafka-go dependency

    Error on M1 Mac when generating mocks with confluent-kafka-go dependency

    Hi, I'm using an M1 mac to generate mocks for a kafka producer which depends on the confluent-kafka-go package. When attempting to generate, moq exits with the below error.

    go generate -tags dynamic ./...
    couldn't load source package: /workspace/mercury/internal/kafka/producers/invalidation_producer.go:94:66: cannot use kafka.PartitionAny (constant unknown with invalid type) as int32 value in struct literal
    

    On non-m1 macs, I can successfully generate the mocks without the -tags dynamic build tag.

  • Generate mocks for interfaces with generic types

    Generate mocks for interfaces with generic types

    Hi!

    I went through the existing issues and was not sure whether one specific to supporting interfaces with generic types exists. I had a look at https://github.com/matryer/moq/issues/168, but this is about generating mocks for types which package uses generics.

    In sum, I would like to have an interface such as:

    //go:generate moq -stub -out publisher_mock.go . Publisher
    
    type Publisher[M any] interface {
    	Publish(ctx context.Context, msg M)
    }
    

    and be able to use a generic mock in my test:

    publisher := PublisherMock[Something]{}
    
    publisher.Publish(ctx, Something{})
    

    Thank you!

HTTP traffic mocking and testing made easy in Go ༼ʘ̚ل͜ʘ̚༽

gock Versatile HTTP mocking made easy in Go that works with any net/http based stdlib implementation. Heavily inspired by nock. There is also its Pyth

Jan 4, 2023
GoMock is a mocking framework for the Go programming language.

gomock GoMock is a mocking framework for the Go programming language. It integrates well with Go's built-in testing package, but can be used in other

Dec 28, 2022
HTTP mocking for Golang

httpmock Easy mocking of http responses from external resources. Install Currently supports Go 1.7 - 1.15. v1 branch has to be used instead of master.

Jan 3, 2023
HTTP mocking to test API services for chaos scenarios
HTTP mocking to test API services for chaos scenarios

GAOS HTTP mocking to test API services for chaos scenarios Gaos, can create and provide custom mock restful services via using your fully-customizable

Nov 5, 2022
A clipboard-based mocking framework for Go that gets out of your way.
A clipboard-based mocking framework for Go that gets out of your way.

A clipboard-based mocking framework for Go that gets out of your way. This tool has been built with inspiration lovingly taken from Moq, and fuelled b

Nov 18, 2022
Lightweight HTTP mocking in Go (aka golang)

httpmock This library builds on Go's built-in httptest library, adding a more mockable interface that can be used easily with other mocking tools like

Dec 16, 2022
Full-featured test framework for Go! Assertions, mocking, input testing, output capturing, and much more! 🍕
Full-featured test framework for Go! Assertions, mocking, input testing, output capturing, and much more! 🍕

testza ?? Testza is like pizza for Go - you could life without it, but why should you? Get The Module | Documentation | Contributing | Code of Conduct

Dec 10, 2022
A simple and expressive HTTP server mocking library for end-to-end tests in Go.

mockhttp A simple and expressive HTTP server mocking library for end-to-end tests in Go. Installation go get -d github.com/americanas-go/mockhttp Exa

Dec 19, 2021
A tool that integrates SQL, HTTP,interface,Redis mock

Mockit 目标:将mock变得简单,让代码维护变得容易 分支介绍 main 主分支,覆盖了单元测试 light 轻分支,去除了单元测试,简化了依赖项,方便其他团队使用 常见Mock难点 不同中间件,mock库设计模式不一致,学习代价高,差异化明显 mock方案强依赖服务端,无法灵活解耦 单元测试

Sep 22, 2022
Package has tool to generate workload for vegeta based kube-api stress tests.

Package has tool to generate workload for vegeta based kube-api stress tests.

Nov 22, 2021
Automatically generate Go test boilerplate from your source code.
Automatically generate Go test boilerplate from your source code.

gotests gotests makes writing Go tests easy. It's a Golang commandline tool that generates table driven tests based on its target source files' functi

Jan 8, 2023
Generate a test coverage badge like this one for your go projects.

coverage-badge-go ?? Generate a test coverage badge like this one for your go projects. Usage on: pull_request: branches: -

Dec 11, 2022
Generate PlantUML diagrams from Chrome or Firefox network inspections

hoofli Generate PlantUML diagrams from Chrome or Firefox network inspections This tool reads browser HAR files stored on your local disk and transform

Nov 15, 2022
go-wrk - a HTTP benchmarking tool based in spirit on the excellent wrk tool (https://github.com/wg/wrk)

go-wrk - an HTTP benchmarking tool go-wrk is a modern HTTP benchmarking tool capable of generating significant load when run on a single multi-core CP

Jan 5, 2023
Fortio load testing library, command line tool, advanced echo server and web UI in go (golang). Allows to specify a set query-per-second load and record latency histograms and other useful stats.
Fortio load testing library, command line tool, advanced echo server and web UI in go (golang). Allows to specify a set query-per-second load and record latency histograms and other useful stats.

Fortio Fortio (Φορτίο) started as, and is, Istio's load testing tool and now graduated to be its own project. Fortio is also used by, among others, Me

Jan 2, 2023
A tool for generating self-contained, type-safe test doubles in go

counterfeiter When writing unit-tests for an object, it is often useful to have fake implementations of the object's collaborators. In go, such fake i

Jan 5, 2023
Lightweight service virtualization/API simulation tool for developers and testers
Lightweight service virtualization/API simulation tool for developers and testers

API simulations for development and testing Hoverfly is a lightweight, open source API simulation tool. Using Hoverfly, you can create realistic simul

Dec 28, 2022
Powerful mock generation tool for Go programming language

Summary Minimock generates mocks out of Go interface declarations. The main features of minimock are: It generates statically typed mocks and helpers.

Dec 17, 2022
A next-generation testing tool. Orion provides a powerful DSL to write and automate your acceptance tests

Orion is born to change the way we implement our acceptance tests. It takes advantage of HCL from Hashicorp t o provide a simple DSL to write the acceptance tests.

Aug 31, 2022