In Go, mocking specific functions declared within concrete types is not feasible. However, you have several options at your disposal to achieve testability:
Function values, present as variables, struct fields, or function parameters, can be mocked in Go. Consider the following:
var Fn = func() { ... } type S struct { Fn func() } func F(Fn func())
In each of these cases, Fn is mockable.
Interfaces provide an effective and preferred means of mocking in Go. Consider the following example:
type ProductRepository interface { GetProductById(DB *sql.DB, ID int) (p Product, err error) } // Real implementation type ProductStore struct{} func (ProductStore) GetProductById(DB *sql.DB, ID int) (p Product, err error) { q := "SELECT * FROM product WHERE id = ?" // ... } // Mock implementation type ProductRepositoryMock struct {} func (ProductRepositoryMock) GetProductById(DB *sql.DB, ID int) (p Product, err error) { // ... }
Code reliant upon ProductRepository can utilize ProductStore for normal execution and ProductRepositoryMock for testing purposes.
To retain most of your function's original structure while enabling mocking, create an interface that mirrors the methods of the type to be passed to your functions. Then, implement both a mock version of the interface and utilize it during testing.
type DBIface interface { Query(query string, args ...interface{}) (*sql.Rows, error) // ... } type DBMock struct {} func (DBMock) Query(query string, args ...interface{}) (*sql.Rows, error) { // ... } func GetProductByName(DB DBIface, name string) (p Product, err error) { ... }
The DB parameter in GetProductByName is now mockable.
The above is the detailed content of How Can I Mock Functions in Go for Effective Testing?. For more information, please follow other related articles on the PHP Chinese website!