我发现了很多关于旧V1包:github.com/jinzhu/gorm的gorm mock的问题。使用github.com/DATA-DOG/go-sqlmock.
我没有发现太多的v2。我的问题很简单:
假设我有这样的存储包代码:
...
type Storage struct {
GormDB *gorm.DB
SqlDB *sql.DB
mutex sync.Mutex
ReadTimeout int
WriteTimeout int
}
func (ps *Storage) Open(settings *Settings) error {
if err := settings.Validate(); err != nil {
return err
}
ps.mutex.Lock()
defer ps.mutex.Unlock()
if ps.GormDB != nil {
return nil
}
gormDB, err := gorm.Open(postgres.New(postgres.Config{
DSN: settings.GetDSN(),
}), &gorm.Config{
SkipDefaultTransaction: true,
})
if err != nil {
return fmt.Errorf("%s: %v", DBConnectError, err)
}
ps.GormDB = gormDB
sqlDB, err := ps.GormDB.DB()
if err != nil {
return fmt.Errorf("%s: %v", DBRetrievalError, err)
}
ps.SqlDB = sqlDB
ps.SqlDB.SetMaxIdleConns(settings.MaxIdleConnections)
ps.SqlDB.SetMaxOpenConns(settings.MaxOpenConnections)
ps.ReadTimeout = settings.ReadTimeout
ps.WriteTimeout = settings.WriteTimeout
return nil
}
我如何用一个简单的检查gorm.Open
是否收到了预期的配置来单元测试这个函数?
除了将ORM接口传递给这个方法外,我看不到任何其他方法…这将是一个艰难的解决方案,写一个gorm接口和模拟它自己…
谁能提供一个简单的模拟这样一个函数的例子?
注:我不想在这个测试中用Postgres运行docker。这是一个简单的单元测试,而不是集成。
编辑:假设我只想模拟连接,使gorm.Open
不返回错误。我该怎么做呢?sqlmock.NewWithDSN(settings.GetDSN())
没有帮助
回答我自己的问题。感谢@flimzy为我指出了正确的方向。
为了能够测试存储打开需要修改函数:
func (ps *Storage) Open(settings *Settings, postgresConfig *postgres.Config) error {
if err := settings.Validate(); err != nil {
return err
}
ps.mutex.Lock()
defer ps.mutex.Unlock()
if ps.GormDB != nil {
return nil
}
gormDB, err := gorm.Open(postgres.New(*postgresConfig), &gorm.Config{
SkipDefaultTransaction: true,
})
if err != nil {
return fmt.Errorf("%s: %v", DBConnectError, err)
}
ps.GormDB = gormDB
sqlDB, err := ps.GormDB.DB()
if err != nil {
return fmt.Errorf("%s: %v", DBRetrievalError, err)
}
ps.SqlDB = sqlDB
ps.SqlDB.SetMaxIdleConns(settings.MaxIdleConnections)
ps.SqlDB.SetMaxOpenConns(settings.MaxOpenConnections)
ps.ReadTimeout = settings.ReadTimeout
ps.WriteTimeout = settings.WriteTimeout
return nil
}
要模拟gorm连接,我们只需在postgres驱动程序的postgres配置中传递go-sqlmock
连接:
package postgres
import (
"github.com/DATA-DOG/go-sqlmock"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Postgres Storage", func() {
...
Describe("Open", func() {
Context("when settings are valid", func() {
It("should open a DB connection and initialize storage", func() {
sqlDB, sqlMock, _ := sqlmock.New()
sqlMock.ExpectPing()
err := storage.Open(settings, postgres.Config{Conn: sqlDB})
dbStats := storage.sqlDB.Stats()
Expect(err).ShouldNot(HaveOccurred())
Expect(dbStats.MaxOpenConnections).To(Equal(settings.MaxOpenConnections))
Expect(dbStats.OpenConnections).To(Equal(1))
Expect(storage.ReadTimeout).To(Equal(settings.ReadTimeout))
Expect(storage.WriteTimeout).To(Equal(settings.WriteTimeout))
Expect(sqlMock.ExpectationsWereMet()).To(BeNil())
})
})
})
})