Giới Thiệu
Bài viết này sẽ hướng dẫn bạn qua một ví dụ toàn diện về cách sử dụng thư viện stretchr/testify
và mockery
trong việc kiểm tra mã nguồn Golang. Chúng ta sẽ khám phá các tính năng chính của stretchr/testify
, bao gồm việc tạo chứng thực kiểm tra, sử dụng gói require
để thực hiện các chứng thực nghiêm ngặt, kiểm tra các bộ xử lý HTTP, và giả lập các phụ thuộc bằng cách sử dụng mockery
.
Tình Huống
Giả sử chúng ta có một dịch vụ giúp truy xuất thông tin người dùng từ một API bên ngoài. Mục tiêu của chúng ta là thử nghiệm:
- Chức năng của dịch vụ.
- Sự tích hợp của nó với một khách hàng bên ngoài.
- Giả lập khách hàng bên ngoài.
Cấu Trúc Dự Án
/project
│
├── main.go
├── service.go
├── service_test.go
├── user_client.go
├── mocks/
│ └── UserClient.go (được tạo ra bởi mockery)
└── go.mod
Tổng Quan Code
1. user_client.go
Tập tin này định nghĩa một giao diện để tương tác với API người dùng bên ngoài.
package project
type User struct {
ID int
Name string
}
type UserClient interface {
GetUserByID(id int) (*User, error)
}
2. service.go
Tập tin này chứa dịch vụ sử dụng UserClient
để truy xuất chi tiết người dùng.
package project
import "fmt"
type UserService struct {
client UserClient
}
func NewUserService(client UserClient) *UserService {
return &UserService{client: client}
}
func (s *UserService) GetUserDetails(id int) (string, error) {
user, err := s.client.GetUserByID(id)
if err != nil {
return "", fmt.Errorf("failed to get user: %w", err)
}
return fmt.Sprintf("User: %s (ID: %d)", user.Name, user.ID), nil
}
3. Tạo Giả Lập Với mockery
Bạn có thể tạo giả lập cho UserClient
bằng cách sử dụng mockery
:
mockery --name=UserClient --output=./mocks
Điều này sẽ tạo ra một giả lập trong mocks/UserClient.go
.
4. service_test.go
Giờ hãy viết một bài kiểm tra cho UserService
bằng cách sử dụng chứng thực testify
và giả lập được tạo ra bởi mockery
.
package project_test
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/mock"
"project"
"project/mocks"
)
func TestUserService_GetUserDetails_Success(t *testing.T) {
// Tạo một khách hàng giả lập mới
mockClient := new(mocks.UserClient)
// Định nghĩa những gì giả lập nên trả về khi `GetUserByID` được gọi
mockClient.On("GetUserByID", 1).Return(&project.User{
ID: 1,
Name: "John Doe",
}, nil)
// Tạo UserService với khách hàng giả lập
service := project.NewUserService(mockClient)
// Thử nghiệm phương thức GetUserDetails
result, err := service.GetUserDetails(1)
// Sử dụng `require` cho các kiểm tra lỗi
require.NoError(t, err)
require.NotEmpty(t, result)
// Sử dụng `assert` cho các kiểm tra giá trị
assert.Equal(t, "User: John Doe (ID: 1)", result)
// Đảm bảo rằng phương thức `GetUserByID` được gọi đúng một lần
mockClient.AssertExpectations(t)
}
func TestUserService_GetUserDetails_Error(t *testing.T) {
// Tạo một khách hàng giả lập mới
mockClient := new(mocks.UserClient)
// Định nghĩa những gì giả lập nên trả về khi `GetUserByID` được gọi với lỗi
mockClient.On("GetUserByID", 2).Return(nil, errors.New("user not found"))
// Tạo UserService với khách hàng giả lập
service := project.NewUserService(mockClient)
// Thử nghiệm phương thức GetUserDetails
result, err := service.GetUserDetails(2)
// Sử dụng `require` cho các kiểm tra lỗi
require.Error(t, err)
assert.Contains(t, err.Error(), "user not found")
// Đảm bảo rằng kết quả là rỗng
assert.Empty(t, result)
// Đảm bảo rằng phương thức `GetUserByID` được gọi đúng một lần
mockClient.AssertExpectations(t)
}
Các Điểm Chính Của Ví Dụ Này
- Chứng Thực Với
testify
:
- Các gói
assert
vàrequire
được sử dụng cho các kiểm tra khác nhau.require
được dùng cho các kiểm tra mà nếu thất bại sẽ làm bài kiểm tra thất bại ngay lập tức (ví dụ: kiểm tra lỗinil
).assert
được dùng cho các kiểm tra có thể tiếp tục ngay cả khi thất bại (ví dụ: so sánh giá trị).
- Giả Lập Với
mockery
:
mockery
tạo ra một giả lập của giao diệnUserClient
.- Trong bài kiểm tra, giả lập được cấu hình bằng
.On()
để chỉ định các đầu vào mong đợi và.Return()
để chỉ định các đầu ra. AssertExpectations
xác minh rằng phương thức giả lập đã được gọi với các đầu vào mong đợi.
- Trong bài kiểm tra, giả lập được cấu hình bằng
- Kiểm Tra Xử Lý Lỗi:
- Một bài kiểm tra kiểm tra kịch bản thành công, trong khi một bài kiểm tra khác kiểm tra cách mà dịch vụ xử lý lỗi từ
UserClient
.
Bố cục này bao quát các chức năng cơ bản của stretchr/testify
cho việc chứng thực và giả lập với mockery
, cung cấp một phương pháp có cấu trúc và dễ bảo trì cho việc kiểm tra đơn vị trong Golang.
Nếu bạn thấy bài viết này hữu ích, hãy cho tôi biết bằng cách để lại 👍 hoặc một bình luận! Nếu bạn nghĩ bài viết này có thể giúp ai đó, hãy tự do chia sẻ! Cảm ơn bạn rất nhiều! 😃
source: viblo