Skip to content
On this page

Mocking

Mocking is a technique used in software testing to create objects that simulate the behavior of real objects. It allows developers to isolate units of code and test them in isolation, without relying on external dependencies. In the Go programming language, one popular testing library for mocking is Testify.

Testify is a widely used testing toolkit for Go that provides a set of utilities and assertions to simplify the testing process. It includes a mocking framework that allows developers to create mock objects and define their behavior for testing purposes. In this document, we will explore how to use Testify's mocking capabilities in Go.

Base on stretchr/testify: A toolkit with common assertions and mocks that plays nicely with the standard library (github.com)

Creating Mock Objects

To create a mock object with Testify, you first need to define an interface that represents the behavior you want to mock. Let's assume we have the following interface representing a data store:

go
type DataStore interface {
    Save(key, value string) error
    Get(key string) (string, error)
    Delete(key string) error
}

To create a mock object that implements this interface, we can use Testify's Mock struct. Here's an example:

go
import (
    "github.com/stretchr/testify/mock"
    "testing"
)

type MockDataStore struct {
    mock.Mock
}

func (m *MockDataStore) Save(key, value string) error {
    args := m.Called(key, value)
    return args.Error(0)
}

func (m *MockDataStore) Get(key string) (string, error) {
    args := m.Called(key)
    return args.String(0), args.Error(1)
}

func (m *MockDataStore) Delete(key string) error {
    args := m.Called(key)
    return args.Error(0)
}

In the example above, we define a MockDataStore struct that embeds testify/mock.Mock, which provides the necessary functionality for mocking. We then implement the methods of the DataStore interface, which delegate the calls to the Called method of the embedded Mock struct. This allows us to record the method calls and return values or errors as needed.

TIP

Mocking for core.IError type

go
func (m *MockRepository[M]) FindOne(conds ...interface{}) (*M, core.IError) {
  args := m.Called(conds...)
  return args.Get(0).(*M), core.MockIError(args, 1)
}

Setting Expectations

Once you have created a mock object, you can set expectations on the method calls using Testify's assertions. Testify provides various assertion methods that allow you to define the expected behavior of the mock object. Here's an example:

go
func TestSaveData(t *testing.T) {
    mockDataStore := new(MockDataStore)
    mockDataStore.On("Save", "key1", "value1").Return(nil)
    // ... code under test ...
    mockDataStore.AssertExpectations(t)
}

In the example above, we create an instance of MockDataStore and set an expectation on the Save method call. We expect the method to be called with the arguments "key1" and "value1" and return nil. The On method is used to set the expectation, and the Return method specifies the return values.

Verifying Method Calls

After executing the code under test, you can use Testify's assertion methods to verify that the expected method calls were made. Testify provides the AssertExpectations method, which checks that all the expected method calls were made. Here's an example:

go
func TestSaveData(t *testing.T) {
    // ... setup mock and set expectations ...
    mockDataStore.AssertExpectations(t)
}

In the example above, we call the AssertExpectations method on the mock object to verify that all the expected method calls were made. If any expectation is not met, the test will fail.

Conclusion

Mocking is an essential technique for unit testing in Go, and Testify provides a convenient and powerful framework for creating and using mock objects. In this document, we covered the basics of creating mock objects using Testify's Mock struct, setting expectations on method calls, and verifying those expectations. By leveraging Testify's mocking capabilities, you can effectively isolate and test your code, leading to more reliable and maintainable software.

Maintained by Passakon Puttasuwan & Dev Core Team.