可测试数据库/sql.go中的行

可测试数据库/sql.go中的行,go,Go,是否有一个测试/模拟函数的良好实践,这些函数执行sql.行扫描到结构中 func parseUsers(r *sql.Rows) (users []User, err error) { for r.Next() { var u User if err = r.Scan(&u.Username, &u.DisplayName, &u.EmailAddress, &

是否有一个测试/模拟函数的良好实践,这些函数执行sql.行扫描到结构中

func parseUsers(r *sql.Rows) (users []User, err error) {
    for r.Next() {
        var u User
        if err = r.Scan(&u.Username,
            &u.DisplayName,
            &u.EmailAddress,
            &u.IsEnabled,
            &u.PhoneNumber); err != nil {
            return []User{}, err
        }
        users = append(users, u)
    }
    err = r.Err()
    return
}
但是试着做一些事情,比如:

func TestParseUsers(t *testing.T) {
    //make mock sql.Rows
    u, err := parseUsers(fakeRows)
    //Do tests...
}
我已经看过sqlx,但希望保留数据库/sql结构。我检查了go sqlmock,但我正在寻找一种没有大量积累的东西


这种测试有好的策略吗?

最好使用一个接口作为输入

在您的情况下,它可能如下所示:

type Scanner interface {
  Next()
  Scan(User)
}
func parseUsers(s Scanner) (users []User, err error) {
  // ...
}
函数应如下所示:

type Scanner interface {
  Next()
  Scan(User)
}
func parseUsers(s Scanner) (users []User, err error) {
  // ...
}

现在测试非常简单,因为您可以创建一个模拟扫描仪,它实现接口并记住调用方法的参数。

方法是使用接口作为输入

在您的情况下,它可能如下所示:

type Scanner interface {
  Next()
  Scan(User)
}
func parseUsers(s Scanner) (users []User, err error) {
  // ...
}
函数应如下所示:

type Scanner interface {
  Next()
  Scan(User)
}
func parseUsers(s Scanner) (users []User, err error) {
  // ...
}

现在测试非常简单,因为您可以创建一个模拟扫描程序,它实现接口并记住调用方法的参数。

这正是我想要的。我确实改变了扫描仪接口的想法,用…接口{}代替结构,但这正是我所需要的!这正是我想要的。我确实改变了扫描仪接口的想法,用…接口{}代替结构,但这正是我所需要的!