DATA-DOG / go-sqlmock

Sql mock driver for golang to test database interactions
Other
6.02k stars 406 forks source link

Gorm V2.0 (v1.20.10) with sqlmock : intermittent rows return with gorm.Create() #248

Closed ibnu-assaumi closed 3 years ago

ibnu-assaumi commented 3 years ago

I found an issue while making insert data unit test with gorm.Create() and sqlmock. It returns intermittent row's position of "updated_at", "created_at", "id" which caused failure sometimes due converting date time type into int64 type. However, if I run the test for several times it can be successful.

struct model :

// MasterData model
type MasterData struct {
    ID         int64  `gorm:"primaryKey;column:id;type:SERIAL"`
    Name       string `gorm:"column:name;type:VARCHAR(50)"`
    RecordProperty
}

// RecordProperty model
type RecordProperty struct {
    CreatedBy int64     `gorm:"column:created_by"`
    CreatedAt time.Time `gorm:"type:TIMESTAMP;default:current_timestamp"`
    UpdatedBy int64     `gorm:"column:updated_by"`
    UpdatedAt time.Time `gorm:"type:TIMESTAMP;default:current_timestamp"`
}

test function :

func Test_InsertMasterData(t *testing.T) {
    t.Run("Success_InsertMasterData", func(t *testing.T) {
        db, dbMock, _ := sqlmock.New()
        gormDB, _ := gorm.Open(postgres.New(postgres.Config{
            Conn: db,
        }), &gorm.Config{})
        now := time.Now()
        repo := &masterRepoSQL{db: db}
        dbMock.ExpectBegin()
        dbMock.ExpectQuery(`INSERT INTO "master_data" (.+) RETURNING`).
            WillReturnRows(sqlmock.NewRows([]string{"created_at", "updated_at", "id"}).AddRow(now, now, int64(1)))
        dbMock.ExpectCommit()
        datamodel := model.MasterData{
            ID:       1,
            Name:     "master_1",
            RecordProperty : model.RecordProperty{
                CreatedAt: now,
                CreatedBy: int64(1),
                UpdatedAt: now,
                UpdatedBy: int64(1),
            }
        }
        err := repo.InsertMasterData(context.Background(), &datamodel)
        assert.NoError(t, err)
        if err := dbMock.ExpectationsWereMet(); err != nil {
            t.Errorf("there were unfulfilled expectations on insert master data : %s", err)
        }
    })
}

log result :

[4.048ms] [rows:0] INSERT INTO "master_data" ("name","created_by","updated_by","updated_at") VALUES ('testing_new_address_type',1,0,0,'2021-01-09 00:16:18.738') RETURNING "id","created_at","updated_at"
--- FAIL: Test_InsertMasterData (0.01s)
    --- FAIL: Test_InsertMasterData/Success_InsertMasterData (0.00s)
        repository_master_data_test.go:204: 
                Error Trace:    repository_master_data_test.go:204
                Error:          Received unexpected error:
                                sql: Scan error on column index 1, name "updated_at": converting driver.Value type time.Time ("2021-01-09 00:16:18.738443 +0700 WIB m=+0.101097980") to a int64: invalid syntax; call to Rollback transaction, was not expected, next expectation is: ExpectedCommit => expecting transaction Commit
                Test:           Test_InsertMasterData/Success_InsertMasterData
        repository_master_data_test.go:206: there were unfulfilled expectations on insert master data : there is a remaining expectation which was not matched: ExpectedCommit => expecting transaction Commit
floyola commented 3 years ago

@ibnu-assaumi did you solve it? I'm having the same issue.