Generate mock implementations using mockery for testing. Use when creating mocks, updating mock interfaces, or setting up test doubles.
This skill guides you through generating and managing mock implementations using mockery.
make mock-gen # Generate all mocks
make mock-clean # Remove all generated mocks
Configuration is in .mockery.yaml:
with-expecter: true # Enable EXPECT() style assertions
testonly: false # Don't add //go:build test constraint
all: false # Don't auto-generate for all interfaces
packages:
app/internal/shared/domain/repository:
interfaces:
UserRepository:
config:
dir: internal/mocks/repository
outpkg: mocks
app/internal/features/auth/usecase:
interfaces:
AuthUsecase:
config:
dir: internal/mocks/usecase
outpkg: mocks
Create your interface in the appropriate package:
// internal/features/product/usecase/product_usecase.go
package usecase
import "app/internal/features/product/delivery/http/dto"
type ProductUsecase interface {
CreateProduct(req *dto.CreateProductRequest) (*dto.ProductResponse, error)
GetProductByID(id string) (*dto.ProductResponse, error)
ListProducts(page, perPage int) ([]dto.ProductResponse, int64, error)
UpdateProduct(id string, req *dto.UpdateProductRequest) (*dto.ProductResponse, error)
DeleteProduct(id string) error
}
Add the interface to .mockery.yaml:
packages:
# ... existing packages ...
app/internal/features/product/usecase:
interfaces:
ProductUsecase:
config:
dir: internal/mocks/usecase
outpkg: mocks
make mock-gen
This creates: internal/mocks/usecase/mock_ProductUsecase.go
package handler
import (
mocks "app/internal/mocks/usecase"
"testing"
"github.com/stretchr/testify/assert"
)
func TestProductHandler_CreateProduct(t *testing.T) {
// Create mock
mockUsecase := mocks.NewMockProductUsecase(t)
// Set expectations
mockUsecase.EXPECT().
CreateProduct(mock.AnythingOfType("*dto.CreateProductRequest")).
Return(&dto.ProductResponse{ID: "123"}, nil).
Once()
// Use mock in tests...
handler := NewProductHandler(mockUsecase)
// ... test code ...
// Verify expectations
mockUsecase.AssertExpectations(t)
}
Repository interfaces are typically in internal/shared/domain/repository/:
packages:
app/internal/shared/domain/repository:
interfaces:
ProductRepository:
config:
dir: internal/mocks/repository
outpkg: mocks
Generated mock: internal/mocks/repository/mock_ProductRepository.go
Use case interfaces are in feature-specific packages:
packages:
app/internal/features/product/usecase:
interfaces:
ProductUsecase:
config:
dir: internal/mocks/usecase
outpkg: mocks
Generated mock: internal/mocks/usecase/mock_ProductUsecase.go
// Exact arguments
mockRepo.EXPECT().
FindByID("123").
Return(user, nil).
Once()
// Any arguments
mockRepo.EXPECT().
Create(mock.AnythingOfType("*entity.User")).
Return(nil).
Once()
// Multiple calls
mockRepo.EXPECT().
List().
Return([]entity.User{}, nil).
Times(3)
import "github.com/stretchr/testify/mock"
// Match any value of type
mock.AnythingOfType("string")
mock.AnythingOfType("*entity.User")
// Custom matcher
mockRepo.EXPECT().
Create(mock.MatchedBy(func(u *entity.User) bool {
return u.Email == "test@example.com"
})).
Return(nil).
Once()
// Anything (any type)
mockRepo.EXPECT().
Update(mock.Anything).
Return(nil).
Once()
// Return single value
mockRepo.EXPECT().
Delete(userID).
Return(nil).
Once()
// Return multiple values
mockRepo.EXPECT().
FindByEmail("test@example.com").
Return(user, nil).
Once()
// Return error
mockRepo.EXPECT().
FindByID("invalid").
Return(nil, gorm.ErrRecordNotFound).
Once()
// Different returns for sequential calls
mockRepo.EXPECT().FindAll().Return([]User{user1}, nil).Once()
mockRepo.EXPECT().FindAll().Return([]User{user1, user2}, nil).Once()
// Called exactly once (default)
mockRepo.EXPECT().Create(user).Return(nil).Once()
// Called exactly N times
mockRepo.EXPECT().Update(user).Return(nil).Times(3)
// Called any number of times (including 0)
mockRepo.EXPECT().GetConfig().Return("config").Maybe()
// internal/features/notification/usecase/notification_usecase.go
package usecase
type NotificationUsecase interface {
SendEmail(to, subject, body string) error
SendSMS(to, message string) error
}
packages:
app/internal/features/notification/usecase:
interfaces:
NotificationUsecase:
config:
dir: internal/mocks/usecase
outpkg: mocks
make mock-gen
package usecase
import (
"app/internal/features/notification/usecase"
mocks "app/internal/mocks/usecase"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestUserUsecase_RegisterWithNotification(t *testing.T) {
// Setup mocks
mockUserRepo := mocks.NewMockUserRepository(t)
mockNotification := mocks.NewMockNotificationUsecase(t)
userUsecase := NewUserUsecase(mockUserRepo, mockNotification)
// Set expectations
mockUserRepo.EXPECT().
Create(mock.AnythingOfType("*entity.User")).
Return(nil).
Once()
mockNotification.EXPECT().
SendEmail(
"newuser@example.com",
"Welcome!",
mock.AnythingOfType("string"),
).
Return(nil).
Once()
// Execute test
err := userUsecase.Register(&RegisterRequest{
Email: "newuser@example.com",
})
// Assert
assert.NoError(t, err)
mockUserRepo.AssertExpectations(t)
mockNotification.AssertExpectations(t)
}
Run make mock-gen after:
# Clean and regenerate all mocks
make mock-clean
make mock-gen
Problem: undefined: mocks.NewMockUserRepository
Solution:
.mockery.yamlmake mock-geninternal/mocks/Problem: Mock generated with wrong package
Solution: Check outpkg in .mockery.yaml:
config:
dir: internal/mocks/repository
outpkg: mocks # Must be "mocks"
Problem: mockery: error: failed to find interface UserRepository
Solution:
.mockery.yaml matches actual packageProblem: Test fails with "FAIL: Expected function call but did not find it"
Solution:
mock.Anything for flexible matching during debugging.Maybe() if call is optionalAssertExpectations(t) at the end of testsOnce() explicitly to catch unexpected multiple calls.mockery.yaml organized with clear package groupingsinternal/mocks/
āāā repository/
ā āāā mock_UserRepository.go
ā āāā mock_ProductRepository.go
ā āāā mock_OrderRepository.go
āāā usecase/
āāā mock_AuthUsecase.go
āāā mock_UserUsecase.go
āāā mock_ProductUsecase.go
This structure keeps mocks organized by layer (repository vs usecase) for easy discovery.