gorm
in v0.12The Dal (Data Access Layer) is designed to decouple the hard dependency on gorm
in v0.12. The advantages of introducing this isolation are:
gorm
directly.gorm
in the future if needed.type Dal interface {
AutoMigrate(entity interface{}, clauses ...Clause) error
Exec(query string, params ...interface{}) error
RawCursor(query string, params ...interface{}) (*sql.Rows, error)
Cursor(clauses ...Clause) (*sql.Rows, error)
Fetch(cursor *sql.Rows, dst interface{}) error
All(dst interface{}, clauses ...Clause) error
First(dst interface{}, clauses ...Clause) error
Count(clauses ...Clause) (int64, error)
Pluck(column string, dest interface{}, clauses ...Clause) error
Create(entity interface{}, clauses ...Clause) error
Update(entity interface{}, clauses ...Clause) error
CreateOrUpdate(entity interface{}, clauses ...Clause) error
CreateIfNotExist(entity interface{}, clauses ...Clause) error
Delete(entity interface{}, clauses ...Clause) error
AllTables() ([]string, error)
}
// Get a database cursor user := &models.User{} cursor, err := db.Cursor( dal.From(user), dal.Where("department = ?", "R&D"), dal.Orderby("id DESC"), ) if err != nil { return err } for cursor.Next() { err = dal.Fetch(cursor, user) // fetch one record at a time ... } // Get a database cursor by raw sql query cursor, err := db.Raw("SELECT * FROM users") // USE WITH CAUTIOUS: loading a big table at once is slow and dangerous // Load all records from database at once. users := make([]models.Users, 0) err := db.All(&users, dal.Where("department = ?", "R&D")) // Load a column as Scalar or Slice var email string err := db.Pluck("email", &username, dal.Where("id = ?", 1)) var emails []string err := db.Pluck("email", &emails) // Execute query err := db.Exec("UPDATE users SET department = ? WHERE department = ?", "Research & Development", "R&D")
err := db.Create(&models.User{ Email: "hello@example.com", // assuming this the Primarykey Name: "hello", Department: "R&D", })
err := db.Create(&models.User{ Email: "hello@example.com", // assuming this the Primarykey Name: "hello", Department: "R&D", })
err := db.CreateOrUpdate(&models.User{ Email: "hello@example.com", // assuming this is the Primarykey Name: "hello", Department: "R&D", })
err := db.CreateIfNotExist(&models.User{ Email: "hello@example.com", // assuming this is the Primarykey Name: "hello", Department: "R&D", })
err := db.CreateIfNotExist(&models.User{ Email: "hello@example.com", // assuming this is the Primary key })
// Returns all table names allTables, err := db.AllTables() // Automigrate: create/add missing table/columns // Note: it won't delete any existing columns, nor does it update the column definition err := db.AutoMigrate(&models.User{})
First, run the command make mock
to generate the Mocking Stubs, the generated source files should appear in mocks
folder.
mocks ├── ApiResourceHandler.go ├── AsyncResponseHandler.go ├── BasicRes.go ├── CloseablePluginTask.go ├── ConfigGetter.go ├── Dal.go ├── DataConvertHandler.go ├── ExecContext.go ├── InjectConfigGetter.go ├── InjectLogger.go ├── Iterator.go ├── Logger.go ├── Migratable.go ├── PluginApi.go ├── PluginBlueprintV100.go ├── PluginInit.go ├── PluginMeta.go ├── PluginTask.go ├── RateLimitedApiClient.go ├── SubTaskContext.go ├── SubTaskEntryPoint.go ├── SubTask.go └── TaskContext.go
With these Mocking stubs, you may start writing your TestCases using the mocks.Dal
.
import "github.com/apache/incubator-devlake/mocks"
func TestCreateUser(t *testing.T) {
mockDal := new(mocks.Dal)
mockDal.On("Create", mock.Anything, mock.Anything).Return(nil).Once()
userService := &services.UserService{
Dal: mockDal,
}
userService.Post(map[string]interface{}{
"email": "helle@example.com",
"name": "hello",
"department": "R&D",
})
mockDal.AssertExpectations(t)