uber-go/mock

repository·main·Indexed 25 days ago

https://github.com/uber-go/mock

A mocking framework for the Go programming language that integrates with the built-in testing package. It includes the mockgen CLI tool to generate mock implementations of interfaces via archive, source, or package modes. The framework provides tools for defining expected calls with assertions and custom behavior using stubs, as well as options for customizing failure message formatting.

Tokens
1.5K
Snippets
6
Records
10
Agent score
36%

What's inside uber-go/mock

  1. Explore GoMock sample implementation

    main

    The sample directory provides a non-trivial example of mocking interfaces. Key files include:

    • user.go: Contains the source code and interfaces to be mocked.
    • user_test.go: Demonstrates how to use mocks, create mock objects, and set up expectations.
    • mock_user_test.go: Contains the generated mock code produced by mockgen.
  2. Install the mockgen tool

    main

    Install the mockgen CLI tool using go install. To verify the installation, run mockgen -version. If the command is not found, ensure your GOPATH/bin is included in your PATH.

    go install go.uber.org/mock/mockgen@latest
    
    # Verify installation
    mockgen -version
    
    # If installation fails, add GOPATH/bin to PATH
    export PATH=$PATH:$(go env GOPATH)/bin
  3. Build mocks and stubs with gomock

    main

    To use mocks in your tests, initialize a controller with gomock.NewController(t) and instantiate the mock using the generated constructor (e.g., NewMockFoo).

    For Assertions (Mocks): Use .EXPECT() to define expected calls and .Return() to specify return values.

    For Behavior (Stubs): Use .EXPECT() with .DoAndReturn() to execute custom logic or .AnyTimes() to allow multiple calls without strict assertion.

    type Foo interface {
      Bar(x int) int
    }
    
    func SUT(f Foo) {
     // ...
    }
    
    // Mock Example (with assertions)
    func TestFoo(t *testing.T) {
      ctrl := gomock.NewController(t)
      m := NewMockFoo(ctrl)
    
      m.EXPECT().
        Bar(gomock.Eq(99)).
        Return(101)
    
      SUT(m)
    }
    
    // Stub Example (with custom behavior)
    func TestFooStub(t *testing.T) {
      ctrl := gomock.NewController(t)
      m := NewMockFoo(ctrl)
    
      m.EXPECT().
        Bar(gomock.Eq(99)).
        DoAndReturn(func(_ int) int {
          time.Sleep(1*time.Second)
          return 101
        }).
        AnyTimes()
    
      SUT(m)
    }
  4. Modify failure message formatting

    main

    You can customize how gomock displays Got and Want values when a matcher fails.

    • Modify Want: Use gomock.WantFormatter with gomock.StringerFunc to change the string representation of the expected value.
    • Modify Got: Use gomock.GotFormatterAdapter with gomock.GotFormatterFunc to change how the actual received value is formatted.
    // Customizing 'Want' output
    gomock.WantFormatter(
      gomock.StringerFunc(func() string { return "is equal to fifteen" }),
      gomock.Eq(15),
    )
    
    // Customizing 'Got' output
    gomock.GotFormatterAdapter(
      gomock.GotFormatterFunc(func(i any) string {
        return fmt.Sprintf("%02d", i)
      }),
      gomock.Eq(15),
    )
  5. Reference mockgen CLI flags

    main

    The mockgen command supports several flags to control the generation process:

    • -archive: A package archive file containing interfaces to be mocked.
    • -source: A file containing interfaces to be mocked.
    • -destination: A file to which to write the resulting source code (defaults to stdout).
    • -package: The package name for the generated code (defaults to mock_ + input package name).
    • -imports: Explicit imports in the format foo=bar/baz (identifier=package path).
    • -aux_files: Additional files to consult for resolving interfaces (format foo=bar/baz.go).
    • -build_flags: Flags passed verbatim to go list (package mode only).
    • -mock_names: Custom names for generated mocks (format Interface=MockName).
    • -self_package: The full package import path for the generated code to prevent import cycles.
    • -copyright_file: Copyright file for the header.
    • -debug_parser: Print out parser results only.
    • -write_package_comment: Writes package documentation comment (default true).
    • -write_generate_directive: Add //go:generate directive (default false).
    • -write_source_comment: Writes original file or interface names comment (default true).
    • -typed: Generate Type-safe 'Return', 'Do', 'DoAndReturn' functions (default false).
    • -exclude_interfaces: Comma-separated names of interfaces to be excluded.
  6. Run mockgen in Package mode

    main
    Package mode is the most common way to use mockgen. It requires an import path and a comma-separated list of symbols. You can use . to refer to the current package, which is ideal for go:generate directives.
  7. Run mockgen in Source mode

    main

    Source mode generates mock interfaces from a specific Go source file using the -source flag. You can also use -imports and -aux_files to provide additional context for resolving interfaces.

    mockgen -source=foo.go [other options]