英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论