Home  >  Article  >  Backend Development  >  Unable to use mockDB (variable of type *MockDB) as *gorm.DB value in struct literal

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

WBOY
WBOYforward
2024-02-14 22:10:08676browse

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

In PHP development, you may encounter problems when using MockDB (a MockDB type variable) as the gorm.DB value in the structure. In this case, MockDB cannot be directly assigned to gorm.DB. This may cause the code to fail to compile or cause runtime errors. Regarding this problem, PHP editor Xigua suggested using other methods to deal with it, such as using type conversion or redesigning the code logic to ensure that the gorm.DB value in the structure can be assigned correctly. Using the correct method to handle this problem can avoid unnecessary errors and exceptions and improve the reliability and stability of the code.

Question content

I have created a get function to get exercises from a postgres database. I wrote a mock test but I get this error from the structure, how can I fix it?

I used the handler structure, which has a *gorm.db structure.

mistake:

Cannot use mockdb (*mockdb type variable) as the *gorm.db value in the structure 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 want to use my handler structure for mock testing

Solution

mockdb and gorm's db are two different structures, you cannot use them interchangeably. If they implement the same interface, they can be used in the same place. 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 *gorm.db to the registerroutes function in your code. For testing purposes, a mockdb structure can be used if it implements all methods in the store interface.

The above is the detailed content of Unable to use mockDB (variable of type *MockDB) as *gorm.DB value in struct literal. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete
Previous article:Using flag pointers in goNext article:Using flag pointers in go