0
0
Lập trình
Admin Team
Admin Teamtechmely

Hướng Dẫn Unit Testing Trong Golang Với Thư Viện Stretchr/testify và Mockery

Đăng vào 1 tuần trước

• 4 phút đọc

Hướng Dẫn Unit Testing Trong Golang Với Thư Viện Stretchr/testify và Mockery

Trong bài viết này, chúng ta sẽ cùng khám phá một ví dụ cụ thể về cách sử dụng thư viện stretchr/testifymockery để thực hiện mocking trong Golang. Bài viết sẽ bao gồm các chủ đề như testing với assertions, sử dụng gói require cho các assertions nghiêm ngặt, kiểm thử HTTP handlers, và mocking các dependencies với mockery.

Kịch Bản Kiểm Thử

Giả sử chúng ta có một dịch vụ cần lấy thông tin người dùng từ một API bên ngoài. Chúng ta sẽ thực hiện kiểm thử cho:

  • Chức năng của dịch vụ.
  • Tích hợp của dịch vụ với một external client.
  • Mocking client bên ngoài.

Cấu Trúc Dự Án

Copy
/project
│
├── main.go
├── service.go
├── service_test.go
├── user_client.go
├── mocks/
│   └── UserClient.go (generated by mockery)
└── go.mod

Tổng Quan Về Source Code

1. user_client.go

File này định nghĩa một interface để tương tác với một external user API.

go Copy
package project

type User struct {
    ID   int
    Name string
}

type UserClient interface {
    GetUserByID(id int) (*User, error)
}

2. service.go

File này chứa một service sử dụng UserClient để lấy thông tin người dùng.

go Copy
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 Mock với Mockery

Để tạo mock cho UserClient, bạn cần sử dụng mockery với lệnh:

bash Copy
mockery --name=UserClient --output=./mocks

Lệnh này sẽ tạo ra một file mock trong thư mục mocks/UserClient.go.

4. service_test.go

Bây giờ, chúng ta sẽ viết test cho UserService sử dụng stretchr/testify để thực hiện assertions và các file mock đã được tạo trước đó bằng mockery.

go Copy
package project_test

import (
    "errors"
    "testing"

    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/require"
    "project"
    "project/mocks"
)

func TestUserService_GetUserDetails_Success(t *testing.T) {
    // Tạo một mock client mới
    mockClient := new(mocks.UserClient)

    // Định nghĩa kết quả mà mock sẽ trả về khi gọi `GetUserByID`
    mockClient.On("GetUserByID", 1).Return(&project.User{
        ID:   1,
        Name: "John Doe",
    }, nil)

    // Tạo UserService với mock client
    service := project.NewUserService(mockClient)

    // Test 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` để kiểm tra giá trị kết quả
    assert.Equal(t, "User: John Doe (ID: 1)", result)

    // Đảm bảo rằng phương thức `GetUserByID` đã được gọi chính xác một lần
    mockClient.AssertExpectations(t)
}

func TestUserService_GetUserDetails_Error(t *testing.T) {
    // Tạo một mock client mới
    mockClient := new(mocks.UserClient)

    // Định nghĩa kết quả mà mock sẽ trả về khi gọi `GetUserByID` và có lỗi xảy ra
    mockClient.On("GetUserByID", 2).Return(nil, errors.New("user not found"))

    // Tạo UserService với mock client
    service := project.NewUserService(mockClient)

    // Test 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 chính xác một lần
    mockClient.AssertExpectations(t)
}

Những Điểm Chính Của Ví Dụ Trên

  1. Assertions Với Testify:

    • Các gói assertrequire được sử dụng để thực hiện kiểm tra khác nhau.
    • require được sử dụng cho các test case mà nếu thất bại thì bài test sẽ dừng lại ngay lập tức.
    • assert được sử dụng cho các test case mà có thể tiếp tục ngay cả khi thất bại.
  2. Mocking Với Mockery:

    • mockery tạo ra một mock cho interface UserClient.
    • Trong bài test, mock được cấu hình bằng .On() để chỉ định đầu vào mong muốn và .Return() để chỉ định đầu ra tương ứng.
    • AssertExpectations xác minh rằng phương thức mock đã được gọi với các đầu vào mong muốn.
  3. Xử Lý Lỗi Trong Kiểm Thử:

    • Một bài test kiểm tra trường hợp thành công, trong khi một bài khác kiểm tra cách dịch vụ xử lý lỗi từ UserClient.

Bài viết này đã cung cấp một cái nhìn tổng quan về các chức năng cơ bản của stretchr/testify cho assertions và mocking với mockery. Đây là một cách tiếp cận có cấu trúc và dễ bảo trì cho việc viết unit tests trong Golang. Cảm ơn bạn đã theo dõi!
source: viblo

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào