无法将类型为*MockDB的变量mockDB用作结构字面值中的*gorm.DB值。

huangapple go评论72阅读模式
英文:

cannot use mockDB (variable of type *MockDB) as *gorm.DB value in struct literal

问题

我为从Postgres数据库获取练习创建了一个获取函数,并编写了模拟测试,但我从结构体中得到了这个错误,我该如何修复它?

我在Handler结构体中使用了*gorm.DB结构体。

错误信息:

无法将mockDB(类型为MockDB的变量)用作结构体字面值中的gorm.DB值

// 路由
package exercises

import (
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

type Handlers struct {
	DB *gorm.DB
}

func RegisterRoutes(router *gin.Engine, db *gorm.DB) {
	h := &Handlers{
		DB: db,
	}

	routes := router.Group("/exercises")
	routes.POST("/", h.AddExercise)
	routes.GET("/", h.GetExercises)
	routes.GET("/:id", h.GetExercise)
	routes.PUT("/:id", h.UpdateExercise)
	routes.DELETE("/:id", h.DeleteExercise)
}

// 测试
package exercises

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/kayraberktuncer/sports-planner/pkg/common/models"
	"github.com/stretchr/testify/mock"
	"gorm.io/gorm"
)

type MockDB struct {
	mock.Mock
}

func (m *MockDB) Find(value interface{}) *gorm.DB {
	args := m.Called(value)
	return args.Get(0).(*gorm.DB)
}

func (m *MockDB) Error() error {
	args := m.Called()
	return args.Error(0)
}

func TestGetExercises(t *testing.T) {
	// 设置模拟的DB
	mockDB := new(MockDB)
	mockDB.On("Find", &[]models.Exercise{}).Return(mockDB).Once()

	// 设置Gin路由
	router := gin.New()
	router.GET("/", func(c *gin.Context) {
		handlers := &Handlers{DB: mockDB} // 错误
		handlers.GetExercises(c)
	})

	// 发送请求
	w := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/", nil)
	router.ServeHTTP(w, req)

	// 断言响应
	if w.Code != http.StatusOK {
		t.Errorf("Expected status code %d, got %d", http.StatusOK, w.Code)
	}

	// 断言模拟的DB被正确调用
	mockDB.AssertExpectations(t)
}

我想使用我的Handler结构体进行模拟测试。

英文:

I created a get function for get exercises from the postgres db. And I wrote mock testing but I got this error from the struct how can I fix it?

I used Handler struct It has *gorm.DB struct.

error:

cannot use mockDB (variable of type *MockDB) as *gorm.DB value in struct literal

// router
package exercises
import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
type Handlers struct {
DB *gorm.DB
}
func RegisterRoutes(router *gin.Engine, db *gorm.DB) {
h := &Handlers{
DB: db,
}
routes := router.Group("/exercises")
routes.POST("/", h.AddExercise)
routes.GET("/", h.GetExercises)
routes.GET("/:id", h.GetExercise)
routes.PUT("/:id", h.UpdateExercise)
routes.DELETE("/:id", h.DeleteExercise)
}
// test
package exercises
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/kayraberktuncer/sports-planner/pkg/common/models"
"github.com/stretchr/testify/mock"
"gorm.io/gorm"
)
type MockDB struct {
mock.Mock
}
func (m *MockDB) Find(value interface{}) *gorm.DB {
args := m.Called(value)
return args.Get(0).(*gorm.DB)
}
func (m *MockDB) Error() error {
args := m.Called()
return args.Error(0)
}
func TestGetExercises(t *testing.T) {
// Setup mock DB
mockDB := new(MockDB)
mockDB.On("Find", &[]models.Exercise{}).Return(mockDB).Once()
// Setup Gin router
router := gin.New()
router.GET("/", func(c *gin.Context) {
handlers := &Handlers{DB: mockDB} // error
handlers.GetExercises(c)
})
// Perform request
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/", nil)
router.ServeHTTP(w, req)
// Assert response
if w.Code != http.StatusOK {
t.Errorf("Expected status code %d, got %d", http.StatusOK, w.Code)
}
// Assert mock DB was called correctly
mockDB.AssertExpectations(t)
}

I wanted to made mock testing with my handler struct

答案1

得分: 3

MockDB和gorm的DB是两个不同的结构体,不能互相替换使用。只有当它们实现了相同的接口时,才可以在同一个地方使用。例如:

// 路由器
package exercises

import (
    "github.com/gin-gonic/gin"
    "gorm.io/gorm"
)

// 这个接口将由gorm.DB结构体实现
type Store interface {
    Create(value interface{}) *gorm.DB
    First(out interface{}, where ...interface{}) *gorm.DB
    Model(value interface{}) *gorm.DB
    Delete(value interface{}, where ...interface{}) *gorm.DB
    Find(out interface{}, where ...interface{}) *gorm.DB
    DB() *sql.DB
    Raw(sql string, values ...interface{}) *gorm.DB
    Exec(sql string, values ...interface{}) *gorm.DB
    Where(query interface{}, args ...interface{}) *gorm.DB
    // 其他方法签名
}

type Handlers struct {
    DB Store
}

func RegisterRoutes(router *gin.Engine, db Store) {
    h := &Handlers{
        DB: db,
    }

    routes := router.Group("/exercises")
    routes.POST("/", h.AddExercise)
    routes.GET("/", h.GetExercises)
    routes.GET("/:id", h.GetExercise)
    routes.PUT("/:id", h.UpdateExercise)
    routes.DELETE("/:id", h.DeleteExercise)
}

现在,你可以在代码中将*gorm.DB传递给RegisterRoutes函数。对于测试,如果MockDB结构体实现了Store接口的所有方法,你可以使用它。

英文:

MockDB and gorm's DB are two different structs and you cannot use them interchangeably. They can be used in the same place if they implement the same interface. For example:

// router
package exercises
import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// this interface will be implemented by gorm.DB struct
type Store interface {
Create(value interface{}) *gorm.DB
First(out interface{}, where ...interface{}) *gorm.DB
Model(value interface{}) *gorm.DB
Delete(value interface{}, where ...interface{}) *gorm.DB
Find(out interface{}, where ...interface{}) *gorm.DB
DB() *sql.DB
Raw(sql string, values ...interface{}) *gorm.DB
Exec(sql string, values ...interface{}) *gorm.DB
Where(query interface{}, args ...interface{}) *gorm.DB
//other method signatures
}
type Handlers struct {
DB Store
}
func RegisterRoutes(router *gin.Engine, db Store) {
h := &Handlers{
DB: db,
}
routes := router.Group("/exercises")
routes.POST("/", h.AddExercise)
routes.GET("/", h.GetExercises)
routes.GET("/:id", h.GetExercise)
routes.PUT("/:id", h.UpdateExercise)
routes.DELETE("/:id", h.DeleteExercise)
}

Now, you can pass the *gorm.DB to the RegisterRoutes function in your code. For testing, you can use your MockDB struct if it implements all of the methods from the Store interface.

huangapple
  • 本文由 发表于 2022年12月28日 04:20:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/74933804.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定