Go Unit Testing: Concepts, Practices, and Patterns
This article introduces the testing pyramid, explains unit testing concepts, and provides a step‑by‑step guide for writing Go unit tests using the standard testing package, the AAA pattern, Testify assertions, mocks, and test suites, while highlighting the benefits of fast verification, documentation, and sustainable development.
Software development relies heavily on testing to ensure code quality. Mike Cohn’s testing pyramid (unit tests at the base, integration in the middle, UI at the top) emphasizes fast, isolated tests. The article uses Go as the primary language to demonstrate how to write effective unit tests.
1. Unit testing concepts – A unit test validates the smallest testable piece of code (function, method, or class). Test fixtures set up known states before each test and clean up afterward.
2. Basic Go unit test – The following code defines a simple Add function and its test using the standard testing package:
package calculator
func Add(v1 int, v2 int) int {
return v1 + v2
} package calculator_test
import (
"testing"
)
func TestAdd(t *testing.T) {
var addTestCases = [][]int{{1, 1, 2}, {1, 0, 1}, {1, -1, 0}, {-1, -1, -2}}
for _, values := range addTestCases {
t.Run("Add testCase", func(t *testing.T) {
result := Add(values[0], values[1])
if result != values[2] {
t.Fatalf("Add error, expected %+v, got %+v", values[2], result)
}
})
}
}The test uses a table‑driven approach, iterating over multiple cases.
3. AAA pattern – Arrange, Act, Assert improves readability. The same test rewritten with explicit sections:
func TestAdd(t *testing.T) {
// arrange
params := []int{1, 2}
expected := "(1,2)"
// act
result := utils.TransIntSliceToSqlIn(params)
// assert
assert.Equal(t, expected, result)
}4. Using Testify – The assert package simplifies assertions, and mock enables test doubles. Example of mocking a repository method:
repo := new(mocks.UserRepository)
repo.On("GetUserInfoByIds", mock.Anything).Return(users, nil)With the mock in place, the service method can be tested without touching a real database.
5. Test suites – When many related tests exist, suite from Testify groups them, providing setup and teardown hooks:
type UserServiceTestSuite struct {
suite.Suite
ctx context.Context
repo *mocks.UserRepository
service *userService.UserService
}
func (s *UserServiceTestSuite) SetupTest() {
s.ctx = context.Background()
s.repo = new(mocks.UserRepository)
s.service = userService.NewUserService(s.repo)
}Running suite.Run(t, new(UserServiceTestSuite)) executes all defined test methods.
6. Significance of unit testing – Fast verification, self‑documenting code, and confidence for refactoring make unit tests essential for sustainable software development.
References include books by Vladimir Khorikov and Mike Cohn, as well as online articles on Go testing best practices.
Xueersi Online School Tech Team
The Xueersi Online School Tech Team, dedicated to innovating and promoting internet education technology.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.