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())
    }
}