Convert Figma logo to code with AI

matryer logomoq

Interface mocking tool for go generate

1,954
126
1,954
23

Top Related Projects

5,959

A mock code autogenerator for Go

9,298

GoMock is a mocking framework for the Go programming language.

22,996

A toolkit with common assertions and mocks that plays nicely with the standard library

3,339

Monkey patching in Go

Quick Overview

Moq is a mock generator for Go. It creates type-safe mocks for interfaces, allowing developers to easily create mock implementations for testing purposes. Moq generates code that can be used to set expectations and verify method calls on mocked interfaces.

Pros

  • Type-safe mocks: Generates mocks that are type-safe and compile-time checked
  • Easy to use: Simple CLI tool that integrates well with Go projects
  • Flexible expectations: Allows setting up various expectations for method calls
  • No runtime dependencies: Generated mocks don't require any external libraries

Cons

  • Limited to interfaces: Can only mock interfaces, not concrete types
  • Manual regeneration: Requires re-running the tool when interfaces change
  • Learning curve: May take some time to understand how to set up complex expectations
  • Limited built-in matchers: Fewer built-in matchers compared to some other mocking libraries

Code Examples

  1. Generating a mock:
//go:generate moq -out user_mock.go . UserRepository

type UserRepository interface {
    GetUser(id int) (*User, error)
    SaveUser(user *User) error
}
  1. Setting up expectations:
mockRepo := &UserRepositoryMock{
    GetUserFunc: func(id int) (*User, error) {
        return &User{ID: id, Name: "John Doe"}, nil
    },
}

user, err := mockRepo.GetUser(1)
  1. Verifying method calls:
mockRepo := &UserRepositoryMock{}
mockRepo.GetUserFunc = func(id int) (*User, error) {
    return &User{ID: id, Name: "Jane Doe"}, nil
}

// Call the method
user, _ := mockRepo.GetUser(2)

// Verify the call
if len(mockRepo.GetUserCalls()) != 1 {
    t.Error("Expected GetUser to be called once")
}
if mockRepo.GetUserCalls()[0].ID != 2 {
    t.Error("Expected GetUser to be called with ID 2")
}

Getting Started

  1. Install Moq:

    go install github.com/matryer/moq@latest
    
  2. Add a go:generate comment to your test file:

    //go:generate moq -out user_mock.go . UserRepository
    
  3. Run go generate:

    go generate ./...
    
  4. Use the generated mock in your tests:

    mockRepo := &UserRepositoryMock{
        GetUserFunc: func(id int) (*User, error) {
            return &User{ID: id, Name: "Test User"}, nil
        },
    }
    // Use mockRepo in your tests
    

Competitor Comparisons

5,959

A mock code autogenerator for Go

Pros of mockery

  • Supports generating mocks for interfaces defined in external packages
  • Offers more customization options for mock generation
  • Provides a command-line interface for easier integration into build processes

Cons of mockery

  • Requires more setup and configuration compared to moq
  • May generate more complex mock code, potentially increasing test file size

Code Comparison

mockery:

//go:generate mockery --name=Repository --output=mocks
type Repository interface {
    GetUser(id int) (*User, error)
}

moq:

//go:generate moq -out mocks_test.go . Repository
type Repository interface {
    GetUser(id int) (*User, error)
}

Both tools use similar code generation comments, but mockery offers more options for customization directly in the comment.

Key Differences

  • mockery is more feature-rich and flexible, while moq focuses on simplicity
  • moq generates mocks in-memory during tests, whereas mockery pre-generates mock files
  • mockery has a larger community and more frequent updates

Use Cases

  • Choose mockery for complex projects with extensive mocking needs
  • Opt for moq in simpler projects or when prioritizing ease of use

Both tools are valuable for generating mocks in Go projects, with the choice depending on specific project requirements and developer preferences.

9,298

GoMock is a mocking framework for the Go programming language.

Pros of mock

  • More mature and widely used in the Go community
  • Supports generating mocks for unexported interfaces
  • Offers more advanced features like call ordering and custom matchers

Cons of mock

  • Requires writing mock implementations manually, which can be time-consuming
  • Syntax can be more verbose and complex for simple mocking scenarios
  • Learning curve may be steeper for beginners

Code Comparison

mock:

ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockObj := mock_package.NewMockInterface(ctrl)
mockObj.EXPECT().Method(gomock.Any()).Return(42)

moq:

mocker := moq.New()
mockObj := mocker.NewMockInterface()
mockObj.MethodFunc = func(arg string) int {
    return 42
}

Key Differences

  • mock uses a controller and expectations, while moq uses function fields
  • mock requires explicit setup of expected calls, whereas moq allows for more flexible function definitions
  • moq generates code that is often more readable and closer to hand-written mocks
  • mock offers more fine-grained control over method call expectations and matching

Use Cases

  • Choose mock for complex mocking scenarios or when working with large, established projects
  • Opt for moq when simplicity and readability are priorities, especially in smaller projects or for developers new to mocking
22,996

A toolkit with common assertions and mocks that plays nicely with the standard library

Pros of testify

  • Comprehensive suite of testing tools, including assertions, mocks, and suites
  • Well-established and widely adopted in the Go community
  • Supports both unit and integration testing

Cons of testify

  • Larger and more complex API compared to moq
  • May introduce additional dependencies to your project
  • Learning curve can be steeper for beginners

Code Comparison

testify mock example:

mock := new(MyMockedObject)
mock.On("DoSomething", 123).Return(true, nil)

moq mock example:

mock := &MyMockedObjectMock{
    DoSomethingFunc: func(arg int) (bool, error) {
        return true, nil
    },
}

Key Differences

  • testify provides a more extensive set of testing utilities, while moq focuses specifically on mocking
  • moq generates type-safe mocks, which can lead to better compile-time checks
  • testify uses a behavior-based mocking approach, whereas moq uses a code generation approach

Use Cases

  • Choose testify for projects requiring a comprehensive testing framework with various assertion types and test organization features
  • Opt for moq when you need lightweight, type-safe mocks and prefer code generation over runtime reflection

Both libraries have their strengths, and the choice depends on your project's specific requirements and your team's preferences.

3,339

Monkey patching in Go

Pros of Monkey

  • Allows mocking of built-in functions and static methods
  • Can patch functions at runtime without changing source code
  • Supports mocking unexported functions

Cons of Monkey

  • Uses runtime patching, which can be unsafe and lead to unexpected behavior
  • May not work with all Go versions or in all environments
  • Can potentially interfere with garbage collection

Code Comparison

Monkey:

patch := monkey.Patch(fmt.Println, func(a ...interface{}) (n int, err error) {
    return 0, nil
})
defer patch.Unpatch()

Moq:

m := &PrinterMock{
    PrintlnFunc: func(a ...interface{}) (n int, err error) {
        return 0, nil
    },
}

Key Differences

Monkey focuses on runtime patching of functions, allowing for more flexibility in what can be mocked, including built-in functions. However, this approach can be riskier and may lead to unexpected behavior.

Moq, on the other hand, generates mock implementations of interfaces at compile-time. This approach is safer and more idiomatic in Go, but it's limited to mocking interfaces and doesn't allow for patching built-in functions or unexported code.

Choose Monkey for maximum flexibility in mocking, especially for built-in functions or unexported code. Opt for Moq when working with interfaces and prioritizing type safety and compile-time checks.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

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 install github.com/matryer/moq@latest

Note that Go 1.18+ is needed for installing from source. For using Moq with older Go versions, use the pre-built binaries published with Moq releases.

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)
  -rm
    	first remove output file, if it exists
  -skip-ensure
    	suppress mock implementation check, avoid import cycle if mocks generated outside of the tested package
  -stub
    	return zero values when no mock implementation is provided, do not panic
  -version
    	show the version for moq
  -with-resets
    	generate functions to facilitate resetting calls made to a mock

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

Ex: 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("me@email.com", mockedEmailSender)

	callsToSend := len(mockedEmailSender.SendCalls())
	if callsToSend != 1 {
		t.Errorf("Send was called %d times", callsToSend)
	}
	if sentTo != "me@email.com" {
		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 .ResetCalls() to reset calls within an individual mock's context
  • 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.