为了账号安全,请及时绑定邮箱和手机立即绑定

单元测试 Postgres 数据库连接 golang

单元测试 Postgres 数据库连接 golang

Go
绝地无双 2022-07-18 16:21:16
即使是为了推动基本的项目结构,我也应该有 80% 的测试覆盖率。我有点困惑如何为以下代码编写单元测试以连接到 postgres db 并 ping postgres 进行健康检查。有人能帮助我吗。var postgres *sql.DB// ConnectToPostgres func to connect to postgresfunc ConnectToPostgres(connStr string) (*sql.DB, error) {    db, err := sql.Open("postgres", connStr)    if err != nil {        log.Println("postgres-client ", err)        return nil, err    }    postgres = db    return db, nil}// PostgresHealthCheck to ping database and check for errorsfunc PostgresHealthCheck() error {    if err := postgres.Ping(); err != nil {        return err    }    return nil}type PostgresRepo struct {    db *sql.DB}// NewPostgresRepo 构造函数func NewPostgresRepo(database *sql.DB) *PostgresRepo {    return &PostgresRepo{        db: database,    }}
查看完整描述

2 回答

?
千巷猫影

TA贡献1829条经验 获得超7个赞

你需要使用这个:https ://github.com/DATA-DOG/go-sqlmock


它非常易于使用。这是一个使用模拟 SQL 测试控制器的示例:


执行

func (up UserProvider) GetUsers() ([]models.User, error) {

    var users = make([]models.User, 0, 10)

    rows, err := up.DatabaseProvider.Query("SELECT firstname, lastname, email, age FROM Users;")

    if err != nil {

        return nil, err

    }

    for rows.Next() {

        var u models.User = models.User{}

        err := rows.Scan(&u.Name, &u.Lastname, &u.Email, &u.Age)

        if err != nil {

            return nil, err

        }

        users = append(users, u)

    }

    if err := rows.Err(); err != nil {

        return nil, err

    }

    return users, nil

}

测试

func TestGetUsersOk(t *testing.T) {

    db, mock := NewMock()

    mock.ExpectQuery("SELECT firstname, lastname, email, age FROM Users;").

        WillReturnRows(sqlmock.NewRows([]string{"firstname", "lastname", "email", "age"}).

            AddRow("pepe", "guerra", "pepe@gmail.com", 34))

    subject := UserProvider{

        DatabaseProvider: repositories.NewMockDBProvider(db, nil),

    }

    resp, err := subject.GetUsers()


    assert.Nil(t, err)

    assert.NotNil(t, resp)

    assert.Equal(t, 1, len(resp))

}


func NewMock() (*sql.DB, sqlmock.Sqlmock) {

    db, mock, err := sqlmock.New()

    if err != nil {

        log.Fatalf("an error '%s' was not expected when opening a stub database connection", err)

    }


    return db, mock

}


查看完整回答
反对 回复 2022-07-18
?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

我发现针对实时数据库编写测试可以实现更高质量的测试。Postgres 面临的挑战是没有可以替代的好的内存伪造品。


我想出的是建立 postgres Docker 容器并在其中创建临时数据库。github.com/bitcomplete/sqltestutil包中的PostgresContainer类型正是这样做的:


# Postgres version is "12"

pg, _ := sqltestutil.StartPostgresContainer(context.Background(), "12")

defer pg.Shutdown(ctx)

db, err := sql.Open("postgres", pg.ConnectionString())

// ... execute SQL

根据文档,设置测试以便容器只启动一次是个好主意,因为启动可能需要几秒钟(如果需要下载图像则需要更多时间)。它提出了一些缓解该问题的方法。


查看完整回答
反对 回复 2022-07-18
  • 2 回答
  • 0 关注
  • 120 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信