Golang Test SQL CRUD

use golang with sqlc to test CRUD


install library

go get github.com/lib/pq
go get github.com/stretchr/testify/require

編寫測試單元

//main_test.go
 
package db
 
import (
 "database/sql"
 "log"
 "os"
 "testing"
 
 _ "github.com/lib/pq"
)
 
var testQueries *Queries
 
const(
 dbDriver = "postgres"
 dbHost = "postgresql://root:password@localhost:5432/simple_bank?sslmode=disable"
)
 
func TestMain(m *testing.M){
 conn,err := sql.Open(dbDriver,dbHost)
 if err != nil {
  log.Println("connnect error")
 }
 testQueries = New(conn)
 os.Exit(m.Run())
}

測試是否能插入數據

//account_test.go
 
package db
 
import (
 "context"
 "testing"
 
 "github.com/stretchr/testify/require"
)
 
func TestAccount(t *testing.T){
 args := CreateAccountParams{
  Owner: "peter",
  Balance: 10000,
  Currency: "NT",
 }
 account,err := testQueries.CreateAccount(context.Background(),args)
 require.NoError(t,err)
 require.NotEmpty(t,account)
 
 require.Equal(t,args.Owner,account.Owner)//檢查args的和輸入的參數比對
 require.Equal(t,args.Balance,account.Balance)
 require.Equal(t,args.Currency,account.Currency)
 
 require.NotZero(t,account.ID)//檢查id自動輸入
 require.NotZero(t,account.CreateAt)//檢查時間自是否自動輸入
}

使用隨機數值來增加新能

  1. 新增util/random
package util
 
import (
 "math/rand"
 "strings"
 "time"
)
 
var alphet = "abcdefghijklmnopqrstuvwxyz"
 
func init(){//init函數將在第一次使用包時自動調用
 rand.Seed(time.Now().UnixNano()) //使用time.Now.UnixNano確保每次值都不一樣
}
 
func RandimInt(min,max int64)int64{
 return min+rand.Int63n(max-min + 1)
 //rand.Int63n(n)會返回0和n-1之間的數
}
 
func RandString(n int)string{
 var sb strings.Builder
 k := len(alphet)
 for i:=0;i<n;i++{
  c := alphet[rand.Intn(k)] //rand.Intn(k)返回0~k-1的隨機位置,並取得那位置的字符
  sb.WriteByte(c) //調用sb.WriteByte將字符c寫入生成器
 }
 return sb.String()
}
 
func RandomOwner()string{
 return RandString(6)
}
 
func RandomMonney()int64{
 return RandimInt(0,1000)
}
 
func RandomCurrency()string{
 currencies := []string{"NT","US","JP"}
 c := len(currencies)
 return currencies[rand.Intn(c)] //返回字符串隨機索引
}

修改測試插入數據

args := CreateAccountParams{
  Owner:util.RandomOwner(),
  Balance: util.RandomMonney(),
  Currency: util.RandomCurrency(),
 }
 account,err := testQueries.CreateAccount(context.Background(),args)
 require.NoError(t,err)
 require.NotEmpty(t,account)
 
 require.Equal(t,args.Owner,account.Owner)//檢查args的和輸入的參數比對
 require.Equal(t,args.Balance,account.Balance)
 require.Equal(t,args.Currency,account.Currency)
 
 require.NotZero(t,account.ID)//檢查id自動輸入
 require.NotZero(t,account.CreateAt)//檢查時間自是否自動輸入
 return account

測試查詢單一數據

func TestGetAccount(t *testing.T){
 account1 := createRandomAccount(t)
 account2,err :=testQueries.GetAccount(context.Background(),account1.ID)
 
 require.NoError(t,err)
 require.NotEmpty(t,account2)
 
 require.Equal(t,account1.ID,account2.ID)
 require.Equal(t,account1.Owner,account2.Owner)
 require.Equal(t,account1.Balance,account2.Balance)
 require.Equal(t,account1.Currency,account2.Currency)
 require.WithinDuration(t,account1.CreateAt.Time,account2.CreateAt.Time, time.Second)
//檢查時間軸是否一樣
}

測試查詢多重數據

func TestListGetAccount(t *testing.T){
 for i := 0; i < 10; i++ {
  createRandomAccount(t)
 }
 
 args := ListAccountsParams{
  Limit: 5,
  Offset: 5,
 }//代表跳過前5項,並返回接下來的5項 =>查詢5項
 account1,err := testQueries.ListAccounts(context.Background(),args)
 require.NoError(t,err)
 require.Len(t,account1,5)//要求返回切片長度為5
 for _,v := range account1{
  require.NotEmpty(t,v)
 }
}

測試修改數據

func TestUpdateAccount(t *testing.T){
 account1 := createRandomAccount(t)
 args := UpdateAuthorBiosParams{
  ID: account1.ID,
  Balance: util.RandomMonney(),
 }
 account2,err := testQueries.UpdateAuthorBios(context.Background(),args)
 require.NoError(t,err)
 require.NotEmpty(t,account2)
 
 require.Equal(t,account1.ID,account2.ID)
 require.Equal(t,account1.Owner,account2.Owner)
 require.Equal(t,args.Balance,account2.Balance)
 require.Equal(t,account1.Currency,account2.Currency)
 require.WithinDuration(t,account1.CreateAt.Time,account2.CreateAt.Time, time.Second)//檢查時間軸是否一樣
}

測試刪除數據

func TestDeleteAccount(t *testing.T){
 account1 := createRandomAccount(t)
 err := testQueries.DeleteAccount(context.Background(),account1.ID)
 require.NoError(t,err)
 
 account2,err := testQueries.GetAccount(context.Background(),account1.ID)
 require.NoError(t,err)
 require.EqualError(t,err,sql.ErrNoRows.Error())
 require.NotEmpty(t,account2)
}