How to Mock in Go: Simple Guide with Examples
In Go, you mock by defining interfaces for the parts you want to replace and then creating mock implementations of those interfaces. Use these mocks in your tests to simulate behavior without calling real dependencies.
Syntax
To mock in Go, first define an interface that describes the methods you want to mock. Then create a struct that implements this interface with mock behavior. Use this mock struct in your tests instead of the real implementation.
This pattern helps isolate the code under test from external dependencies.
go
type Service interface { DoSomething(input string) (string, error) } // Mock struct implementing Service type MockService struct { MockDoSomething func(input string) (string, error) } func (m *MockService) DoSomething(input string) (string, error) { return m.MockDoSomething(input) }
Example
This example shows how to use a mock to test a function that depends on a Service interface. The mock returns a fixed response without calling real code.
go
package main import ( "errors" "fmt" ) type Service interface { DoSomething(input string) (string, error) } type RealService struct{} func (r *RealService) DoSomething(input string) (string, error) { return "Real: " + input, nil } type MockService struct { MockDoSomething func(input string) (string, error) } func (m *MockService) DoSomething(input string) (string, error) { return m.MockDoSomething(input) } func Process(s Service, input string) (string, error) { return s.DoSomething(input) } func main() { // Using real service real := &RealService{} result, _ := Process(real, "hello") fmt.Println(result) // Using mock service mock := &MockService{ MockDoSomething: func(input string) (string, error) { if input == "fail" { return "", errors.New("mock error") } return "Mocked: " + input, nil }, } res1, err1 := Process(mock, "test") fmt.Println(res1, err1) res2, err2 := Process(mock, "fail") fmt.Println(res2, err2) }
Output
Real: hello
Mocked: test <nil>
<nil> mock error
Common Pitfalls
- Not using interfaces: Without interfaces, you cannot easily replace real implementations with mocks.
- Mocking too much: Mock only external dependencies, not the code you want to test.
- Complex mocks: Keep mocks simple and focused on the behavior needed for the test.
- Ignoring errors: Always handle errors in mocks to test failure cases.
go
/* Wrong: Using concrete type directly, no interface */ // func Process(s *RealService, input string) (string, error) { // return s.DoSomething(input) // } /* Right: Use interface to allow mocking */ type Service interface { DoSomething(input string) (string, error) } func Process(s Service, input string) (string, error) { return s.DoSomething(input) }
Quick Reference
Remember these steps to mock in Go:
- Define an interface for the dependency.
- Create a mock struct implementing the interface.
- Implement mock methods with custom behavior.
- Use the mock in your tests to simulate different scenarios.
Key Takeaways
Always define interfaces to enable mocking in Go.
Create simple mock structs implementing those interfaces for tests.
Use mocks to simulate both success and error cases.
Avoid mocking your own code; mock only external dependencies.
Keep mocks focused and easy to maintain.