Тестирование Cookie вернулось из функции в Go

Я пытаюсь протестировать функцию, которая извлекает Cookie из запроса в Go, однако, хотя они имеют одинаковое значение, сравнение не удается.

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)
    }
}

Ссылка для детской площадки: https://play.golang.org/p/T4dbZycMuT

Я проверил документацию по функции DeepEqual и из того, что я вижу, 2 структуры / указатель должны быть одинаковыми (особенно если учесть, что в Cookie нет неэкспортируемых полей).

Я могу изменить функцию для сравнения строк cookie, однако я хотел бы знать, есть ли простое объяснение, почему это не работает или это происходит из-за "несоответствия", как указано в документации. Также есть ли способ проверить структуру, а не строковое представление в этом сценарии (или я допустил ошибку, может быть)?

2 ответа

Решение

Сравнение файлов cookie с reflect.DeepEquals это очень плохая идея. Тип 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() {

С помощью 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)}

Raw значение проанализированного cookie заполняется, а созданный cookie не имеет Raw ценность, понятно.

Детская площадка: https://play.golang.org/p/ghzkjUoEGW

Другие вопросы по тегам