2 回答

TA貢獻1831條經驗 獲得超10個贊
“如何進行單元測試”是一個非常廣泛的問題,因為它取決于你想要測試什么。在您的示例中,您正在處理與數據庫的遠程連接,這通常是在單元測試中被嘲笑的東西。目前尚不清楚這是否是您要尋找的,也不是必需的。通過看到你使用不同的數據庫,我希望其意圖不是嘲笑。
首先看看這篇文章,它已經回答了你關于TestMain和打算如何工作的問題。testing.M
您的代碼當前所做的(如果您的測試名稱正確命名)是在其他測試周圍添加一個方法來執行設置和拆卸,但是您沒有任何其他測試來使用此設置和拆卸,因此您將獲得結果。TestMainno tests to run
這不是你問題的一部分,但我建議盡量避免,直到你對測試Go代碼有信心。使用和測試單獨的單元可能更容易理解。你可以通過調用你的測試并讓初始值設定項接受一個參數來實現幾乎相同的事情。testing.Mtesting.TinitDB()
func initDB(dbToUse string) {
// ...
db.Exec("USE "+dbToUse)
}
然后,您將從主文件和測試中調用。您可以在 pkg.go.dev/testing 閱讀有關 Go 的測試包的信息,您還可以在其中找到 和 之間的差異。initDB("test")initDB("test111")testing.Ttesting.M
下面是一個簡短的示例,其中包含一些基本測試,這些測試不需要任何設置或拆卸,而是使用 代替 。testing.Ttesting.M
主要.go
package main
import "fmt"
func main() {
fmt.Println(add(1, 2))
}
func add(a, b int) int {
return a + b
}
main_test
package main
import "testing"
func TestAdd(t *testing.T) {
t.Run("add 2 + 2", func(t *testing.T) {
want := 4
// Call the function you want to test.
got := add(2, 2)
// Assert that you got your expected response
if got != want {
t.Fail()
}
})
}
此測試將測試您的方法,并確保它在作為參數傳遞時返回正確的值。使用 是可選的,但它會為您創建一個子測試,這使得讀取輸出更容易一些。add2, 2t.Run
由于在包級別進行測試,因此,如果不以遞歸方式使用三點格式(包括每個包),則需要指定要測試的包。
若要運行上述示例中的測試,請指定包和詳細輸出。-v
$ go test ./ -v
=== RUN TestAdd
=== RUN TestAdd/add_2_+_2
--- PASS: TestAdd (0.00s)
--- PASS: TestAdd/add_2_+_2 (0.00s)
PASS
ok x (cached)
圍繞這個主題還有很多東西需要學習,比如測試框架和測試模式。例如,測試框架testify可以幫助您進行斷言,并在測試失敗時打印出漂亮的輸出,并且表驅動的測試是Go中非常常見的模式。
您還在編寫HTTP服務器,該服務器通常需要額外的測試設置才能正確測試。幸運的是,標準庫中的包帶有一個名為httptest的子包,它可以幫助您記錄外部請求或為外部請求啟動本地服務器。還可以通過使用手動構造的請求直接調用處理程序來測試處理程序。http
它看起來像這樣。
func TestSomeHandler(t *testing.T) {
// Create a request to pass to our handler. We don't have any query parameters for now, so we'll
// pass 'nil' as the third parameter.
req, err := http.NewRequest("GET", "/some-endpoint", nil)
if err != nil {
t.Fatal(err)
}
// We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
rr := httptest.NewRecorder()
handler := http.HandlerFunc(SomeHandler)
// Our handlers satisfy http.Handler, so we can call their ServeHTTP method
// directly and pass in our Request and ResponseRecorder.
handler.ServeHTTP(rr, req)
// Check the status code is what we expect.
if status := rr.Code; status != http.StatusOK {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusOK)
}
現在,測試一些代碼。我們可以運行 init 方法,并使用響應記錄器調用您的任何服務。
package main
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
func TestGetAllJobs(t *testing.T) {
// Initialize the DB
initDB("test111")
req, err := http.NewRequest("GET", "/GetAllJobs", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
handler := http.HandlerFunc(GetAllJobs)
handler.ServeHTTP(rr, req)
// Check the status code is what we expect.
if status := rr.Code; status != http.StatusOK {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusOK)
}
var response []Jobs
if err := json.Unmarshal(rr.Body.Bytes(), &response); err != nil {
t.Errorf("got invalid response, expected list of jobs, got: %v", rr.Body.String())
}
if len(response) < 1 {
t.Errorf("expected at least 1 job, got %v", len(response))
}
for _, job := range response {
if job.SourcePath == "" {
t.Errorf("expected job id %d to have a source path, was empty", job.JobID)
}
}
}

TA貢獻1852條經驗 獲得超1個贊
你可以使用 go-sqlmock:
package main
import (
"database/sql"
"regexp"
"testing"
"gopkg.in/DATA-DOG/go-sqlmock.v1"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Student struct {
//*gorm.Model
Name string
ID string
}
type v2Suite struct {
db *gorm.DB
mock sqlmock.Sqlmock
student Student
}
func TestGORMV2(t *testing.T) {
s := &v2Suite{}
var (
db *sql.DB
err error
)
db, s.mock, err = sqlmock.New()
if err != nil {
t.Errorf("Failed to open mock sql db, got error: %v", err)
}
if db == nil {
t.Error("mock db is null")
}
if s.mock == nil {
t.Error("sqlmock is null")
}
dialector := postgres.New(postgres.Config{
DSN: "sqlmock_db_0",
DriverName: "postgres",
Conn: db,
PreferSimpleProtocol: true,
})
s.db, err = gorm.Open(dialector, &gorm.Config{})
if err != nil {
t.Errorf("Failed to open gorm v2 db, got error: %v", err)
}
if s.db == nil {
t.Error("gorm db is null")
}
s.student = Student{
ID: "123456",
Name: "Test 1",
}
defer db.Close()
s.mock.MatchExpectationsInOrder(false)
s.mock.ExpectBegin()
s.mock.ExpectQuery(regexp.QuoteMeta(
`INSERT INTO "students" ("id","name")
VALUES ($1,$2) RETURNING "students"."id"`)).
WithArgs(s.student.ID, s.student.Name).
WillReturnRows(sqlmock.NewRows([]string{"id"}).
AddRow(s.student.ID))
s.mock.ExpectCommit()
if err = s.db.Create(&s.student).Error; err != nil {
t.Errorf("Failed to insert to gorm db, got error: %v", err)
}
err = s.mock.ExpectationsWereMet()
if err != nil {
t.Errorf("Failed to meet expectations, got error: %v", err)
}
}
- 2 回答
- 0 關注
- 234 瀏覽
添加回答
舉報