moq

repository·main·Indexed 24 days ago

https://github.com/matryer/moq

An interface mocking tool for Go that uses `go generate` to create mock structs. It allows developers to control dependency behavior in unit tests by providing function implementations for interface methods, featuring a CLI for generation and options for call tracking, stubbing, and resetting.

Tokens
1.8K
Snippets
8
Records
11
Agent score
81%

What's inside moq

  1. Best practices and troubleshooting for Moq

    main

    Best Practices

    • Scope: Keep mocked logic inside the specific test that uses it.
    • Minimalism: Only mock the fields/methods you actually need for the test.
    • Capturing Data: Use closures inside your test functions to capture arguments passed to mock methods.
    • Call Tracking: Use .MethodCalls() to track how many times a method was called and with what arguments.
    • Resetting: Use .ResetCalls() (requires the -with-resets flag during generation) to clear call history within a single mock's context.
    • Interface Naming: Name arguments in your interface clearly; Moq uses these names in the generated function signatures, which improves the developer experience.

    Troubleshooting

    • Nil Panics: Moq will panic if a method is called but no implementation was provided for that function field. Use the -stub flag during generation to return zero values instead of panicking.
    • Formatting Errors: If Moq fails with a go/format error, the generated code is invalid. Run the command with -fmt noop to see the raw generated source and debug the cause.
  2. Install Moq

    main

    To install the latest released version of Moq, use the go install command. Note that Go 1.18+ is required for installing from source. For older Go versions, use the pre-built binaries from the official Moq releases page.

    $ go install github.com/matryer/moq@latest
  3. Release a new version of Moq

    main

    To release a new version, you must first tag the repository and push the tag to origin, then run GoReleaser with a valid GITHUB_TOKEN.

    1. Tag the repository:
    git tag -a v0.1.0 -m "release tag."
    git push origin v0.1.0
    1. Run GoReleaser:
    GITHUB_TOKEN=xxx goreleaser --clean
    #!/bin/bash
    git tag -a v0.1.0 -m "release tag."
    git push origin v0.1.0
    GITHUB_TOKEN=xxx goreleaser --clean
  4. Install GoReleaser for Moq releases

    main

    Moq uses GoReleaser to manage its release builds. To prepare for releasing, you must install GoReleaser and configure your GitHub credentials.

    1. Install GoReleaser via Homebrew:
    brew install goreleaser/tap/goreleaser
    1. Create a New personal access token on GitHub and export it as the GITHUB_TOKEN environment variable.
    brew install goreleaser/tap/goreleaser
  5. Integrate Moq with go generate

    main

    You can automate mock generation by adding a //go:generate directive directly above your interface definition in your Go source files. This allows you to run go generate ./... to refresh your mocks.

    package my
    
    //go:generate moq -out myinterface_moq_test.go . MyInterface
    
    type MyInterface interface {
    	Method1() error
    	Method2(i int)
    }
  6. Test GoReleaser configuration changes

    main

    If you are modifying the GoReleaser configuration and want to verify the changes without actually publishing anything, use the --snapshot and --skip=publish flags.

    goreleaser --snapshot --skip=publish --clean
  7. How to use generated mocks in tests

    main

    Moq creates a struct where each interface method is represented by a function field. In your tests, you assign a function to these fields to define the mock's behavior. You can use captured variables from the test scope to verify interactions.

    func TestCompleteSignup(t *testing.T) { 
    	var sentTo string
    
    	// Initialize the mock with custom behavior
    	mockedEmailSender = &EmailSenderMock{
    		SendFunc: func(to, subject, body string) error {
    			sentTo = to
    			return nil
    		},
    	}
    
    	CompleteSignUp("me@email.com", mockedEmailSender)
    
    	// Verify behavior using call tracking
    	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)
    	}
    }
  8. Moq CLI Reference

    main

    Available flags for the moq command:

    FlagDescription
    -fmt stringGo pretty-printer: gofmt, goimports or noop (default gofmt)
    -out stringOutput file (default stdout)
    -pkg stringPackage name (default will infer)
    -rmRemove the output file first, if it exists
    -skip-ensureSuppress mock implementation check; avoids import cycles if mocks are generated outside the tested package
    -stubReturn zero values when no mock implementation is provided instead of panicking
    -versionShow the version for moq
    -with-resetsGenerate functions to facilitate resetting calls made to a mock
  9. Use the Moq CLI

    main
    The Moq CLI generates a struct from a specified interface to be used as a mock in tests. The command requires a source-dir (the directory path containing the interface definition, not the import path) and the name of the interface.
  10. Reference: moq CLI flags

    main

    The following flags are available for the moq command:

    FlagDescription
    -outOutput file path (defaults to stdout)
    -pkgPackage name for the generated mock (defaults to inferring from source)
    -fmtGo pretty-printer to use: gofmt, goimports, or noop (defaults to gofmt)
    -stubIf set, mock functions return zero values instead of panicking when no implementation is provided
    -versionShow the current version of moq
    -skip-ensureSuppress mock implementation check; useful to avoid import cycles if mocks are generated outside the tested package
    -rmRemove the output file if it already exists before generating the new one
    -with-resetsGenerate functions to facilitate resetting calls made to a mock
    moq [flags] source-dir interface [interface2 [interface3 [...]]]
    
    Specifying an alias for the mock is also supported with the format 'interface:alias'
    Ex: moq -pkg different . MyInterface:MyMock
  11. Use the moq CLI to generate mocks

    main

    The moq command generates mock implementations for Go interfaces. The basic syntax requires a source directory and one or more interfaces. You can also specify an alias for a mock using the interface:alias format.

    Usage: moq [flags] source-dir interface [interface2 [interface3 [...]]]

    Example: To generate a mock named MyMock for an interface named MyInterface in the current directory and save it to a specific package:

    moq -pkg different . MyInterface:MyMock
    moq -pkg different . MyInterface:MyMock