Как имитировать вставку gorm с помощью go-sql (postgres)

Я использую Gorm с драйвером postgresql. Я пытаюсь имитировать вставку в базу данных с помощью go-sqlmock:

type Test struct {
    FirstName string `json:"first_name"`
}

func (db *DB) CreateTest() (*Test, error) {
    test := Test{"c"}
    if result := db.Create(&test); result.Error != nil {
        return nil, result.Error
    }

    return &test, nil
}


func TestCreateUser(t *testing.T) {
    _, mock, _ := sqlmock.NewWithDSN("sqlmock_db_0")

    mockedGorm, _ := gorm.Open("sqlmock", "sqlmock_db_0")
    defer mockedGorm.Close()
    myDB := &DB{mockedGorm}

    mock.ExpectExec("INSERT INTO test").WithArgs("c").WillReturnResult(sqlmock.NewResult(1, 1))
    myDB.Exec("INSERT INTO test(first_name) VALUES (?)", "c")


    if _, err := myDB.CreateTest(); err != nil {
        t.Errorf("error was not expected: %s", err)
    }

    if err := mock.ExpectationsWereMet(); err != nil {
        t.Errorf("there were unfulfilled expectations: %s", err)
    }
}

К сожалению, это дает мне ошибку:

error was not expected: all expectations were already fulfilled, call to database transaction Begin was not expected

Как правильно протестировать вставку с помощью gorm, postgresql и sql-mock?

1 ответ

Решение

В моем коде было несколько проблем:

1) Как справедливо указал @flimzy, должен быть ExpectBegin() (а также ExpectCommit()) заявление. Это становится более очевидным, если включить отладчик GORM, который показывает, что именно делает GORM.

2) ExpectExec("INSERT INTO test").WithArgs("c") совершенно очевидно не совпадает myDB.Exec("INSERT INTO test(first_name) VALUES (?)", "c")

3) Следует избегать оператора, поскольку go-sqlmock принимает регулярное выражение, здесь вам пригодится https://godoc.org/regexp Go.

Рабочий код:

mock.ExpectBegin()
mock.ExpectExec(regexp.QuoteMeta("INSERT INTO \"tests\" (\"first_name\") VALUES (?)")).WithArgs("c").WillReturnResult(sqlmock.NewResult(1, 1))
mock.ExpectCommit()
Другие вопросы по тегам