GOLANG INTEGRATION TEST VỚI GIN, GORM, TESTIFY, MYSQL

0 0 0

Người đăng: Truong Phung

Theo Viblo Asia

Trong bài này chúng ta sẽ viết một chương trình integration test cơ bản cho ứng dụng Golang sử dụng các thư viện như Gin, Gorm, Testify, và MySQL (sử dụng giải pháp in-memory) bao gồm việc setup môi trường testing, định nghĩa các routes và handlers, và test chúng với một real database (mặc dù việc dùng MySQL in-memory có thể cần đến giải pháp thay thế như sử dụng SQLite ở chế độ in-memory để cho đơn giản hơn).

Dưới đây là ví dụ về cách thiết lập một chương trình integration test:

1. Dependencies:

  • Gin: dùng để tạo HTTP server.
  • Gorm: dùng cho ORM để tương tác với cơ sở dữ liệu.
  • Testify: dùng để hỗ trợ kiểm tra (assertions).
  • SQLite in-memory: đóng vai trò thay thế cho MySQL trong quá trình kiểm thử.

2. Setup:

  • Định nghĩa một model cơ bản và thiết lập Gorm.
  • Tạo HTTP routes và handlers.
  • Viết các bài test sử dụng TestifySQLite như một in-memory database.

Dưới đây là ví dụ đầy đủ:

// main.go
package main import ( "github.com/gin-gonic/gin" "gorm.io/driver/mysql" "gorm.io/driver/sqlite" "gorm.io/gorm" "net/http"
) // User represents a simple user model.
type User struct { ID uint `gorm:"primaryKey"` Name string `json:"name"` Email string `json:"email" gorm:"unique"`
} // SetupRouter initializes the Gin engine with routes.
func SetupRouter(db *gorm.DB) *gin.Engine { r := gin.Default() // Inject the database into the handler r.POST("/users", func(c *gin.Context) { var user User if err := c.ShouldBindJSON(&user); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := db.Create(&user).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, user) }) r.GET("/users/:id", func(c *gin.Context) { var user User id := c.Param("id") if err := db.First(&user, id).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) return } c.JSON(http.StatusOK, user) }) return r
} func main() { // For production, use MySQL dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") } db.AutoMigrate(&User{}) r := SetupRouter(db) r.Run(":8080")
}

Integration Test

// main_test.go
package main import ( "bytes" "encoding/json" "github.com/stretchr/testify/assert" "net/http" "net/http/httptest" "testing" "gorm.io/driver/sqlite" "gorm.io/gorm"
) // SetupTestDB sets up an in-memory SQLite database for testing.
func SetupTestDB() *gorm.DB { db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) if err != nil { panic("failed to connect to the test database") } db.AutoMigrate(&User{}) return db
} func TestCreateUser(t *testing.T) { db := SetupTestDB() r := SetupRouter(db) // Create a new user. user := User{Name: "John Doe", Email: "john@example.com"} jsonValue, _ := json.Marshal(user) req, _ := http.NewRequest("POST", "/users", bytes.NewBuffer(jsonValue)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() r.ServeHTTP(w, req) assert.Equal(t, http.StatusCreated, w.Code) var createdUser User json.Unmarshal(w.Body.Bytes(), &createdUser) assert.Equal(t, "John Doe", createdUser.Name) assert.Equal(t, "john@example.com", createdUser.Email)
} func TestGetUser(t *testing.T) { db := SetupTestDB() r := SetupRouter(db) // Insert a user into the in-memory database. user := User{Name: "Jane Doe", Email: "jane@example.com"} db.Create(&user) // Make a GET request. req, _ := http.NewRequest("GET", "/users/1", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) assert.Equal(t, http.StatusOK, w.Code) var fetchedUser User json.Unmarshal(w.Body.Bytes(), &fetchedUser) assert.Equal(t, "Jane Doe", fetchedUser.Name) assert.Equal(t, "jane@example.com", fetchedUser.Email)
} func TestGetUserNotFound(t *testing.T) { db := SetupTestDB() r := SetupRouter(db) // Make a GET request for a non-existent user. req, _ := http.NewRequest("GET", "/users/999", nil) w := httptest.NewRecorder() r.ServeHTTP(w, req) assert.Equal(t, http.StatusNotFound, w.Code)
} 

Giải thích

  1. main.go:
  • Định nghĩa một User struct và thiết lập các thao tác CRUD cơ bản sử dụng Gin.
  • Sử dụng Gorm để tương tác với cơ sở dữ liệu và tự động migrate bảng User.
  • SetupRouter cấu hình các HTTP endpoint.
  1. main_test.go:
  • SetupTestDB thiết lập SQLite in-memory database cho việc testing.
  • TestCreateUser: Test việc tạo một user.
  • TestGetUser: Test việc lấy một user đã tồn tại.
  • TestGetUserNotFound: Test việc lấy một user không tồn tại.
  • Sử dụng httptest.NewRecorderhttp.NewRequest để giả lập các request và response HTTP.
  • Sử dụng Testify để kiểm tra, như test HTTP status code và xác minh phản hồi JSON.

Khởi chạy chương trình test

Để run test, sử dụng lệnh:

go test -v

Lưu ý

  • SQLite for In-memory Testing: Ví dụ này sử dụng SQLite cho việc kiểm thử in-memoryMySQL không hỗ trợ chế độ in-memory với Gorm. Đối với các chương trình test cần phụ thuộc vào các tính năng cụ thể của MySQL, cân nhắc sử dụng giải pháp dựa trên Docker với một container MySQL.
  • Database Migrations: Luôn đảm bảo schema của cơ sở dữ liệu được cập nhật bằng cách sử dụng AutoMigrate trong các chương trình test.
  • Isolation: Mỗi hàm test sẽ khởi tạo một in-memory database mới, đảm bảo các hàm test không gây ảnh hưởng lẫn nhau.

Bình luận

Bài viết tương tự

- vừa được xem lúc

gRPC - Nó là gì và có nên sử dụng hay không?

Nhân một ngày rảnh rỗi, mình ngồi đọc lại RPC cũng như gRPC viết lại để nhớ lâu hơn. Vấn đề là gì và tại sao cần nó .

0 0 129

- vừa được xem lúc

Embedded Template in Go

Getting Start. Part of developing a web application usually revolves around working with HTML as user interface.

0 0 55

- vừa được xem lúc

Tạo Resful API đơn giản với Echo framework và MySQL

1. Giới thiệu.

0 0 59

- vừa được xem lúc

Sử dụng goquery trong golang để crawler thông tin các website Việt Nam bị deface trên mirror-h.org

. Trong bài viết này, mình sẽ cùng mọi người khám phá một package thu thập dữ liệu có tên là goquery của golang. Mục tiêu chính của chương trình crawler này sẽ là lấy thông tin các website Việt Nam bị deface (là tấn công, phá hoại website, làm thay đổi giao diện hiển thị của một trang web, khi người

0 0 235

- vừa được xem lúc

Tạo ứng dụng craw dữ liệu bing với Golang, Mysql driver

Chào mọi người . Lâu lâu ta lại gặp nhau 1 lần, để tiếp tục series chia sẻ kiến thức về tech, hôm nay mình sẽ tìm hiểu và chia sẻ về 1 ngôn ngữ đang khá hot trong cộng đồng IT đó là Golang.

0 0 75

- vừa được xem lúc

Golang: Rest api and routing using MUX

Routing with MUX. Let's create a simple CRUD api for a blog site. # All . GET articles/ .

0 0 53