GOLANG INTEGRATION TEST WITH GIN, GORM, TESTIFY, MYSQL

0 0 0

Người đăng: Truong Phung

Theo Viblo Asia

Creating a comprehensive integration test for a Golang application using libraries like Gin, Gorm, Testify, and MySQL (using an in-memory solution) involves setting up a testing environment, defining routes and handlers, and testing them against an actual database (though using MySQL in-memory might require a workaround like using SQLite in in-memory mode for simplicity).

Here’s an example of an integration test setup:

1. Dependencies:

  • Gin: for creating the HTTP server.
  • Gorm: for ORM to interact with the database.
  • Testify: for assertions.
  • SQLite in-memory: acts as a substitute for MySQL during testing.

2. Setup:

  • Define a basic model and Gorm setup.
  • Create HTTP routes and handlers.
  • Write tests using Testify and SQLite as an in-memory database.

Here’s the full example:

// 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)
} 

Explanation

  1. main.go:
  • Defines a User struct and sets up basic CRUD operations using Gin.
  • Uses Gorm for database interactions and auto-migrates the User table.
  • SetupRouter configures HTTP endpoints.
  1. main_test.go:
  • SetupTestDB initializes an in-memory SQLite database for isolated testing.
  • TestCreateUser: Tests the creation of a user.
  • TestGetUser: Tests fetching an existing user.
  • TestGetUserNotFound: Tests fetching a non-existent user.
  • Uses httptest.NewRecorder and http.NewRequest for simulating HTTP requests and responses.
  • Uses Testify for assertions, like checking HTTP status codes and verifying JSON responses.

Running the Tests

To run the tests, use:

go test -v

Considerations

  • SQLite for In-memory Testing: This example uses SQLite for in-memory testing as MySQL doesn't natively support an in-memory mode with Gorm. For tests that rely on MySQL-specific features, consider using a Docker-based setup with a MySQL container.
  • Database Migrations: Always ensure the database schema is up-to-date using AutoMigrate in tests.
  • Isolation: Each test function initializes a fresh in-memory database, ensuring tests don't interfere with each other.

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