我用go写了一个简单的post请求处理程序,它工作正常,但是当我运行它的单元测试时,它抛出了错误。与db的连接:
var err error
server.DBConn, err = sql.Open("mysql", "root:root@tcp(localhost:8889)/infomatrix_project")
defer server.DBConn.Close()
http.HandleFunc("/reg_startup", post.RegStartup)
http.ListenAndServe(":9000", nil)
处理程序函数:
type Startup struct {
Name string `json:"name"`
Login string `json:"login"`
Password string `json:"password"`
Email string `json:"email"`
Description string `json:"description"`
Logo string `json:"logo"`
LowestInvestment int `json:"lowestInvestment"`
HighestInvestment int `json:"highestInvestment"`
Region string `json:"region"`
WebSite string `json:"website"`
Industry string `json:"industry"`
}
func RegStartup(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
if r.Method != "POST" {
fmt.Fprintf(w, "error: the request is not a POST type")
return
}
//other.AccessSetter(w)
var query Startup
err := json.NewDecoder(r.Body).Decode(&query)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
stmt, err := server.DBConn.Prepare("INSERT INTO startups (name, login, password, email, " +
"description, logo, lowest_investment, highest_investment, region, website, industry) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
defer stmt.Close()
if err != nil {
log.Fatal(err)
return
}
_, err = stmt.Exec(query.Name, query.Login, query.Password, query.Email, query.Description, query.Logo,
query.LowestInvestment, query.HighestInvestment, query.Region, query.WebSite, query.Industry)
if err != nil {
log.Fatal(err)
return
}
fmt.Fprintf(w, "data entered successfully")
}
测试功能:
func TestRegStartup(t *testing.T) {
load := Startup{"название на кириллице", "test_startup", "test_password", "test@example.com", "This is a test startup.",
"https://example.com/test_startup_logo.jpg", 1000, 10000, "Kazakhstan", "https://teststartup.com", "IT"}
loadBytes, _ := json.Marshal(load)
request, err := http.NewRequest("POST", "/reg_startup", bytes.NewBuffer(loadBytes))
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
handler := http.HandlerFunc(postRequests.RegStartup)
handler.ServeHTTP(rr, request)
status := rr.Code
if status != http.StatusOK {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusOK)
return
}
expected := `"data entered successfully"`
if rr.Body.String() != expected {
t.Errorf("handler returned unexpected body: got %v want %v",
rr.Body.String(), expected)
return
}
}
错误:
--- FAIL: TestRegStartup (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x102534408]
goroutine 18 [running]:
testing.tRunner.func1.2({0x1025bfa40, 0x102723f80})
/usr/local/go/src/testing/testing.go:1526 +0x1c8
testing.tRunner.func1()
/usr/local/go/src/testing/testing.go:1529 +0x384
panic({0x1025bfa40, 0x102723f80})
/usr/local/go/src/runtime/panic.go:884 +0x204
database/sql.(*DB).conn(0x1025a4c9c?, {0x1025f75b8?, 0x1400009c018?}, 0xe0?)
/usr/local/go/src/database/sql/sql.go:1282 +0x28
database/sql.(*DB).prepare(0x140000e8190?, {0x1025f75b8, 0x1400009c018}, {0x102549c1b, 0xb1}, 0x0?)
/usr/local/go/src/database/sql/sql.go:1587 +0x34
database/sql.(*DB).PrepareContext.func1(0xa0?)
/usr/local/go/src/database/sql/sql.go:1561 +0x48
database/sql.(*DB).retry(0x140000d5c28?, 0x140000d5be8)
/usr/local/go/src/database/sql/sql.go:1538 +0x4c
database/sql.(*DB).PrepareContext(0x140000e8168?, {0x1025f75b8?, 0x1400009c018?}, {0x102549c1b?, 0x140000d5c01?})
/usr/local/go/src/database/sql/sql.go:1560 +0x74
database/sql.(*DB).Prepare(0x140000e8140?, {0x102549c1b?, 0x140000baaa0?})
/usr/local/go/src/database/sql/sql.go:1577 +0x40
github.com/SayatAbdikul/rest_api_for_startup/postRequests.RegStartup({0x1025f73a0, 0x140000a8ac0}, 0x14000104000)
/Users/sayat/Documents/GitHub/rest_api_for_startup/postRequests/regStartup.go:38 +0x1d4
net/http.HandlerFunc.ServeHTTP(...)
/usr/local/go/src/net/http/server.go:2122
github.com/SayatAbdikul/rest_api_for_startup/package_test_test.TestRegStartup(0x14000082d00)
/Users/sayat/Documents/GitHub/rest_api_for_startup/package_test/regStartup_test.go:37 +0x1c0
testing.tRunner(0x14000082d00, 0x1025f4db8)
/usr/local/go/src/testing/testing.go:1576 +0x10c
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:1629 +0x368
FAIL github.com/SayatAbdikul/rest_api_for_startup/package_test 0.515s
--- FAIL: TestRegStartup (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x0 pc=0x102371168]
goroutine 18 [running]:
testing.tRunner.func1.2({0x102467a40, 0x1025cbfa0})
/usr/local/go/src/testing/testing.go:1526 +0x1c8
testing.tRunner.func1()
/usr/local/go/src/testing/testing.go:1529 +0x384
panic({0x102467a40, 0x1025cbfa0})
/usr/local/go/src/runtime/panic.go:884 +0x204
database/sql.(*DB).conn(0x10244cc9c?, {0x10249f5b8?, 0x14000112018?}, 0x60?)
/usr/local/go/src/database/sql/sql.go:1282 +0x28
database/sql.(*DB).prepare(0x14000160190?, {0x10249f5b8, 0x14000112018}, {0x1023f1c8b, 0xb1}, 0x0?)
/usr/local/go/src/database/sql/sql.go:1587 +0x34
database/sql.(*DB).PrepareContext.func1(0x40?)
/usr/local/go/src/database/sql/sql.go:1561 +0x48
database/sql.(*DB).retry(0x1400014bc18?, 0x1400014bbd8)
/usr/local/go/src/database/sql/sql.go:1538 +0x4c
database/sql.(*DB).PrepareContext(0x14000160168?, {0x10249f5b8?, 0x14000112018?}, {0x1023f1c8b?, 0x1400014bc01?})
/usr/local/go/src/database/sql/sql.go:1560 +0x74
database/sql.(*DB).Prepare(0x14000160140?, {0x1023f1c8b?, 0x14000130b40?})
/usr/local/go/src/database/sql/sql.go:1577 +0x40
github.com/SayatAbdikul/rest_api_for_startup/postRequests.RegStartup({0x10249f3a0, 0x14000120ac0}, 0x1400017c000)
/Users/sayat/Documents/GitHub/rest_api_for_startup/postRequests/regStartup.go:38 +0x1d4
net/http.HandlerFunc.ServeHTTP(...)
/usr/local/go/src/net/http/server.go:2122
github.com/SayatAbdikul/rest_api_for_startup/postRequests_test.TestRegStartup(0x1400011e9c0)
/Users/sayat/Documents/GitHub/rest_api_for_startup/postRequests/regStartup_test.go:38 +0x1c0
testing.tRunner(0x1400011e9c0, 0x10249cdc0)
/usr/local/go/src/testing/testing.go:1576 +0x10c
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:1629 +0x368
FAIL github.com/SayatAbdikul/rest_api_for_startup/postRequests 0.935s
FAIL
我尝试将连接更改为db(连接是通过ip连接到服务器,我将其更改为localhost),并尝试更改test的位置。错误没有改变。
1条答案
按热度按时间vhipe2zx1#
让我来分享一下我的解决方案,以及一些关于编写和测试Go代码的见解。通常,我遵循这种方式,但可能有更好的方法来管理它。代码包含在两个文件中。让我们从生产代码开始。
handlers/handlers.go
文件这里的代码与您的代码非常相似。我简化了
Startup
结构以处理更少的字段。最重要的是将*sql.DB
传递给处理函数。这是通过上下文来完成的,这是实现它的最佳方法之一。在main.go
文件中,您可以自由设置超时时间,以便在超时时取消每个正在进行的呼叫。请记住,当您从上下文中获取时,始终检查
nil
值(以及值的类型!).handlers/handlers_test.go
文件测试代码需要更多的解释:
1.您应该依靠
sqlmock
包来处理数据库使用情况。您可以指定如何匹配查询/命令以及它们应该返回哪些结果。1.您必须创建
http.ResponseWriter
和*http.Request
来调用RegStartup
函数。您可以轻松使用httptest
包。1.确保按预期设置HTTP请求。
1.将
*sql.DB
包添加到HTTP请求的上下文。如果使用
go test -v -cover
命令运行测试,一切都应该按预期工作。当然,还有很多东西需要改进,但这一点可能是一个很好的起点,以更好的方式实现HTTP处理程序和测试。如果您需要更多细节或澄清,请随时询问,谢谢!