测试从Go函数返回的Cookie

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

Testing Cookie returned from Function in Go

问题

我正在尝试测试一个从Go请求中获取Cookie的函数,但是尽管它们具有相同的值,比较却失败了。

package main

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"
	"reflect"
)

func GetCookie(url string) *http.Cookie {
	req, err := http.NewRequest("GET", url, nil)
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	client := http.DefaultClient

	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	cookies := res.Cookies()
	var mycookie *http.Cookie
	for _, c := range cookies {
		if c.Name == "mycookie" {
			mycookie = c
		}
	}

	return mycookie
}

func main() {
	validCookie := &http.Cookie{
		Name:     "mycookie",
		Value:    "SomeValue",
		Path:     "/mysite",
		HttpOnly: true,
		Secure:   true,
	}

	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.SetCookie(w, validCookie)
		w.Header().Set("Content-Type", "text/plain")
		w.WriteHeader(200)
	}))
	defer ts.Close()

	fmt.Printf("EqualL Cookies: %t\n", reflect.DeepEqual(validCookie, validCookie))

	if got := GetCookie(ts.URL); !reflect.DeepEqual(got, validCookie) {
		log.Fatalf("NOT THE SAME\n got = '%v'\nwant = '%v'", got, validCookie)
	}
}

我已经查看了DeepEqual函数的文档,从我所看到的来看,这两个结构体/指针应该是相同的(特别是Cookie没有未导出的字段)。

我可以更改函数来比较Cookie的字符串表示,但我想知道为什么这样不起作用,或者是因为文档中指定的"不一致性"导致的。在这种情况下,是否有任何方法可以测试结构体而不是字符串表示(或者我可能犯了一个错误)?

英文:

I am attempting to test a function that retrieves a Cookie from a request in Go however even though they have the same value, the comparison fails.

package main
import (
"fmt"
"log"
"net/http"
"net/http/httptest"
"reflect"
)
func GetCookie(url string) *http.Cookie {
req, err := http.NewRequest("GET", url, nil)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
client := http.DefaultClient
res, err := client.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
cookies := res.Cookies()
var mycookie *http.Cookie
for _, c := range cookies {
if c.Name == "mycookie" {
mycookie = c
}
}
return mycookie
}
func main() {
validCookie := &http.Cookie{
Name:     "mycookie",
Value:    "SomeValue",
Path:     "/mysite",
HttpOnly: true,
Secure:   true,
}
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, validCookie)
w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(200)
}))
defer ts.Close()
fmt.Printf("EqualL Cookies: %t\n", reflect.DeepEqual(validCookie, validCookie))
if got := GetCookie(ts.URL); !reflect.DeepEqual(got, validCookie) {
log.Fatalf("NOT THE SAME\n got = '%v'\nwant = '%v'", got, validCookie)
}
}

Playground link: https://play.golang.org/p/T4dbZycMuT

I have checked the documentation on the DeepEqual function and from what I can see the 2 structs/pointer should be the same (Specially given that Cookie has no unexported fields).

I can change the function to compare the Cookie Strings however I would like to know if there is a simple explanation why this does not work or is it due to "inconsistency" as the documentation specifies.
Also is there any way to test for the struct rather than the string representation in this scenarion (Or did I make a mistake maybe)?

答案1

得分: 3

使用fmt.Printf("%#v")显示了问题:

got=        &http.Cookie{Name:"mycookie", Value:"SomeValue", Path:"/mysite", Domain:"", Expires:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, RawExpires:"", MaxAge:0, Secure:true, HttpOnly:true, Raw:"mycookie=SomeValue; Path=/mysite; HttpOnly; Secure", Unparsed:[]string(nil)}
validCookie=&http.Cookie{Name:"mycookie", Value:"SomeValue", Path:"/mysite", Domain:"", Expires:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, RawExpires:"", MaxAge:0, Secure:true, HttpOnly:true, Raw:"", Unparsed:[]string(nil)}

解析后的 cookie 的 Raw 值已填充,而构造的 cookie 没有 Raw 值,这是可以理解的。

Playground: https://play.golang.org/p/ghzkjUoEGW

英文:

Using fmt.Printf("%#v") shows the issue:

got=        &http.Cookie{Name:"mycookie", Value:"SomeValue", Path:"/mysite", Domain:"", Expires:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, RawExpires:"", MaxAge:0, Secure:true, HttpOnly:true, Raw:"mycookie=SomeValue; Path=/mysite; HttpOnly; Secure", Unparsed:[]string(nil)}
validCookie=&http.Cookie{Name:"mycookie", Value:"SomeValue", Path:"/mysite", Domain:"", Expires:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, RawExpires:"", MaxAge:0, Secure:true, HttpOnly:true, Raw:"", Unparsed:[]string(nil)}

The Raw value of the parsed cookie is filled, while the constructed cookie has no Raw value, understandably.

Playground: https://play.golang.org/p/ghzkjUoEGW

答案2

得分: 3

使用reflect.DeepEquals来比较Cookie是一个非常糟糕的主意。http.Cookie类型包含的组件在解析和/或操作方式不同的情况下,无法转换为Cookie的字面头表示。

如果你将代码更改为使用%#v

if got := GetCookie(ts.URL); !reflect.DeepEqual(got, validCookie) {
    log.Fatalf("NOT THE SAME\n got = '%#v'\nwant = '%#v'", got, validCookie)
}

...你会看到差异:

EqualL Cookies: true
2009/11/10 23:00:00 NOT THE SAME
got = '&http.Cookie{Name:"mycookie", Value:"SomeValue", Path:"/mysite", Domain:"", Expires:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, RawExpires:"", MaxAge:0, Secure:true, HttpOnly:true, Raw:"mycookie=SomeValue; Path=/mysite; HttpOnly; Secure", Unparsed:[]string(nil)}'
want = '&http.Cookie{Name:"mycookie", Value:"SomeValue", Path:"/mysite", Domain:"", Expires:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, RawExpires:"", MaxAge:0, Secure:true, HttpOnly:true, Raw:"", Unparsed:[]string(nil)}'

相反,直接比较URL字符串:

if got := GetCookie(ts.URL); got.String() == validCookie.String() {
英文:

Comparing Cookies with reflect.DeepEquals is a very bad idea. The http.Cookie type contains components that do not translate into the literal header representation of the cookie, depending on how it's parsed and/or manipulated.

If you change your code to use %#v:

if got := GetCookie(ts.URL); !reflect.DeepEqual(got, validCookie) {
log.Fatalf("NOT THE SAME\n got = '%#v'\nwant = '%#v'", got, validCookie)
}

... you'll see the difference:

EqualL Cookies: true
2009/11/10 23:00:00 NOT THE SAME
got = '&http.Cookie{Name:"mycookie", Value:"SomeValue", Path:"/mysite", Domain:"", Expires:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, RawExpires:"", MaxAge:0, Secure:true, HttpOnly:true, Raw:"mycookie=SomeValue; Path=/mysite; HttpOnly; Secure", Unparsed:[]string(nil)}'
want = '&http.Cookie{Name:"mycookie", Value:"SomeValue", Path:"/mysite", Domain:"", Expires:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, RawExpires:"", MaxAge:0, Secure:true, HttpOnly:true, Raw:"", Unparsed:[]string(nil)}'

Instead, just compare the URL strings directly:

if got := GetCookie(ts.URL); got.String() == validCookie.String() {

huangapple
  • 本文由 发表于 2017年9月16日 03:59:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/46246728.html
匿名

发表评论

匿名网友

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

确定