doc.dev1x.org

sqlxとsqlmockを用いたDB操作モジュールのユニットテスト

概要

sqlmockを用いたsqlxのモック化サンプルコード

テスト対象モジュール

type ItemRepository struct {
    db  *sqlx.DB
}

func (r *ItemRepository) FindAll() (model.ItemList, error) {

    rows, err := r.db.Queryx(`SELECT * FROM item`)
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    var itemList model.ItemList
    var item model.Item
    for rows.Next() {
        err := rows.StructScan(&item)
        if err != nil {
            return nil, err
        }
        itemList = append(itemList, item)
    }
    return itemList, nil
}

モックDB生成関数

func NewMockDB(t *testing.T) (*sqlx.DB, sqlmock.Sqlmock) {

    t.Helper()

    mockDB, mock, err := sqlmock.New()
    if err != nil {
        t.Error("MockDB Initialize Failed.")
    }

    sqlxDB := sqlx.NewDb(mockDB, "sqlmock")
    return sqlxDB, mock
}

テストコード

func Test_1(t *testing.T) {
    // mock initialize.
    db, mock := NewMockDB(t)
    defer db.Close()
    repos := &ItemRepository{db}

    // mock setup.
    mock.ExpectQuery(
        regexp.QuoteMeta(`SELECT * FROM item`),
    ).WillReturnRows(
        sqlmock.NewRows([]string{""}),
    )

    // do exec.
    _, err := repos.FindAll()
    if err != nil {
        t.Error(err.Error())
    }

    if err := mock.ExpectationsWereMet(); err != nil {
        t.Error(err.Error())
    }
}