html/template golang面临无效内存地址错误的单元测试

huangapple go评论76阅读模式
英文:

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."

huangapple
  • 本文由 发表于 2022年8月21日 13:04:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/73431763.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定