英文:
Unit test for html/template golang facing invalid memory address error
问题
所以我有一个简单的应用程序,应该在GET
请求/login/
上呈现一个Html页面。当我在本地运行Web服务器时,请求工作正常,但是当我运行单元测试时似乎出现了错误。(使用go test -v
来运行测试。)
--- FAIL: TestLoginRequest (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=0x1 addr=0x20 pc=0x76ddf0]
goroutine 8 [running]:
testing.tRunner.func1.2({0x841660, 0xbeb720})
/usr/local/go/src/testing/testing.go:1396 +0x24e
testing.tRunner.func1()
/usr/local/go/src/testing/testing.go:1399 +0x39f
panic({0x841660, 0xbeb720})
/usr/local/go/src/runtime/panic.go:884 +0x212
html/template.(*Template).lookupAndEscapeTemplate(0x0, {0xc000036640, 0x4c})
/usr/local/go/src/html/template/template.go:146 +0x50
html/template.(*Template).ExecuteTemplate(0x8ab914?, {0x7faf3da99c78, 0xc0001c4340}, {0xc000036640?, 0x0?}, {0x8148c0, 0xc0001beee0})
/usr/local/go/src/html/template/template.go:135 +0x38
github.com/vedicsociety/brucheion.renderLoginTemplate({0x9691b8?, 0xc0001c4340}, {0x8ab914?, 0xbff840?}, 0xc0001a0600?)
/home/abdurrehman/Documents/work/martin-gluckman/Brucheion/templates.go:52 +0x85
github.com/vedicsociety/brucheion.loginGET({0x9691b8, 0xc0001c4340}, 0xc0001b8900?)
/home/abdurrehman/Documents/work/martin-gluckman/Brucheion/login.go:72 +0x325
net/http.HandlerFunc.ServeHTTP(0xc0001a0500?, {0x9691b8?, 0xc0001c4340?}, 0x203000?)
/usr/local/go/src/net/http/server.go:2109 +0x2f
github.com/gorilla/mux.(*Router).ServeHTTP(0xc0001c80c0, {0x9691b8, 0xc0001c4340}, 0xc0001a0400)
/home/abdurrehman/go/pkg/mod/github.com/gorilla/mux@v1.7.4/mux.go:210 +0x1cf
github.com/vedicsociety/brucheion.executeRequest(0x8aa772?)
/home/abdurrehman/Documents/work/martin-gluckman/Brucheion/api_test.go:41 +0xaf
github.com/vedicsociety/brucheion.TestLoginRequest(0x0?)
/home/abdurrehman/Documents/work/martin-gluckman/Brucheion/api_test.go:32 +0x7f
testing.tRunner(0xc0000d7860, 0x8ea660)
/usr/local/go/src/testing/testing.go:1446 +0x10b
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:1493 +0x35f
exit status 2
FAIL github.com/vedicsociety/brucheion 0.005s
单元测试
func TestLoginRequest(t *testing.T) {
setupRouter()
req, _ := http.NewRequest("GET", "/login/", nil)
response := executeRequest(req)
assert.Equal(t, 200, response.Code)
}
// Helper functions.
func executeRequest(req *http.Request) *httptest.ResponseRecorder {
requestRecorder := httptest.NewRecorder()
router.ServeHTTP(requestRecorder, req)
return requestRecorder
}
func setupRouter() {
router = mux.NewRouter().StrictSlash(true)
router.HandleFunc("/login/", loginGET).Methods("GET")
router.NotFoundHandler = http.HandlerFunc(NotFoundRedirect)
}
问题似乎出在这里
func renderLoginTemplate(res http.ResponseWriter, tmpl string, loginPage *LoginPage) {
fmt.Println(generateFilePath(tmpl))
err := templates.ExecuteTemplate(res, generateFilePath(tmpl), loginPage)
if err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
}
}
func generateFilePath(tName string) string {
s, err := os.Getwd()
if err != nil {
panic(err)
}
return filepath.Join(s, "/tmpl/", tName+".html")
}
templates.ExecuteTemplate
函数有问题。我遇到了这两个 StackOverflow 的问题(链接1,链接2),开发者似乎遇到了相同的问题,因此创建了 generateFilePath
函数来获取绝对路径,但是没有成功。
英文:
So I have a simple application that is supposed to render an Html page on GET
requests /login/
. The requests work fine when I run the web server locally, but when I run unit tests there seems to be an error.(go test -v
is being used to run the tests.)
--- FAIL: TestLoginRequest (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=0x1 addr=0x20 pc=0x76ddf0]
goroutine 8 [running]:
testing.tRunner.func1.2({0x841660, 0xbeb720})
/usr/local/go/src/testing/testing.go:1396 +0x24e
testing.tRunner.func1()
/usr/local/go/src/testing/testing.go:1399 +0x39f
panic({0x841660, 0xbeb720})
/usr/local/go/src/runtime/panic.go:884 +0x212
html/template.(*Template).lookupAndEscapeTemplate(0x0, {0xc000036640, 0x4c})
/usr/local/go/src/html/template/template.go:146 +0x50
html/template.(*Template).ExecuteTemplate(0x8ab914?, {0x7faf3da99c78, 0xc0001c4340}, {0xc000036640?, 0x0?}, {0x8148c0, 0xc0001beee0})
/usr/local/go/src/html/template/template.go:135 +0x38
github.com/vedicsociety/brucheion.renderLoginTemplate({0x9691b8?, 0xc0001c4340}, {0x8ab914?, 0xbff840?}, 0xc0001a0600?)
/home/abdurrehman/Documents/work/martin-gluckman/Brucheion/templates.go:52 +0x85
github.com/vedicsociety/brucheion.loginGET({0x9691b8, 0xc0001c4340}, 0xc0001b8900?)
/home/abdurrehman/Documents/work/martin-gluckman/Brucheion/login.go:72 +0x325
net/http.HandlerFunc.ServeHTTP(0xc0001a0500?, {0x9691b8?, 0xc0001c4340?}, 0x203000?)
/usr/local/go/src/net/http/server.go:2109 +0x2f
github.com/gorilla/mux.(*Router).ServeHTTP(0xc0001c80c0, {0x9691b8, 0xc0001c4340}, 0xc0001a0400)
/home/abdurrehman/go/pkg/mod/github.com/gorilla/mux@v1.7.4/mux.go:210 +0x1cf
github.com/vedicsociety/brucheion.executeRequest(0x8aa772?)
/home/abdurrehman/Documents/work/martin-gluckman/Brucheion/api_test.go:41 +0xaf
github.com/vedicsociety/brucheion.TestLoginRequest(0x0?)
/home/abdurrehman/Documents/work/martin-gluckman/Brucheion/api_test.go:32 +0x7f
testing.tRunner(0xc0000d7860, 0x8ea660)
/usr/local/go/src/testing/testing.go:1446 +0x10b
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:1493 +0x35f
exit status 2
FAIL github.com/vedicsociety/brucheion 0.005s
unit test
func TestLoginRequest(t *testing.T) {
setupRouter()
req, _ := http.NewRequest("GET", "/login/", nil)
response := executeRequest(req)
assert.Equal(t, 200, response.Code)
}
// Helper functions.
func executeRequest(req *http.Request) *httptest.ResponseRecorder {
requestRecorder := httptest.NewRecorder()
router.ServeHTTP(requestRecorder, req)
return requestRecorder
}
func setupRouter() {
router = mux.NewRouter().StrictSlash(true)
router.HandleFunc("/login/", loginGET).Methods("GET")
router.NotFoundHandler = http.HandlerFunc(NotFoundRedirect)
}
The issue seems to be here
func renderLoginTemplate(res http.ResponseWriter, tmpl string, loginPage *LoginPage) {
fmt.Println(generateFilePath(tmpl))
err := templates.ExecuteTemplate(res, generateFilePath(tmpl), loginPage)
if err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
}
}
func generateFilePath(tName string) string {
s, err := os.Getwd()
if err != nil {
panic(err)
}
return filepath.Join(s, "/tmpl/", tName+".html")
}
The templates.ExecuteTemplate
function is being problematic. I came across these two StackOverflow questions (link1, link2) where the developer seems to have encountered the same issue and thus created the function generateFilePath to get an absolute path haven't had any luck.
答案1
得分: 0
http.NewRequest
返回一个 *http.Request
实例,用于 客户端 发送 出站请求。loginGET
是一个处理程序,它期望一个用于 服务器 的 *http.Request
实例,用于 入站请求。请勿将 http.NewRequest
的输出直接作为 ServeHTTP
的参数。
对于处理程序测试,不要使用 http.NewRequest
,而是使用 httptest.NewRequest
:"NewRequest 返回一个新的 入站服务器请求,适用于传递给 http.Handler 进行测试。"
英文:
http.NewRequest
returns an instance of *http.Request
that is intended for clients to send outgoing requests. loginGET
is a handler that expects an instance of *http.Request
intended for servers, for an incoming request. Do NOT use the output of http.NewRequest
as a direct argument to ServeHTTP
.
For handler tests, instead of http.NewRequest
, use httptest.NewRequest
: "NewRequest returns a new incoming server Request, suitable for passing to an http.Handler for testing."
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论