1

In trying to set up two different web.Request states for use in some test cases, one without any headers and one with, I run into issue:

Setup

I create fakeRequest,fakeRequestNoHeaders thus:

// create fake request
fakeRequest := new(web.Request)
fakeRequest.Request = httptest.NewRequest("GET",
    fakeServer.URL,
    nil)

fakeRequestNoHeaders := new(web.Request)
fakeRequestNoHeaders.Request = fakeRequest.Request

// give fakeRequest some headers
fakeRequest.Header.Add("Authorization", "Bearer ksjaf;oipyu7")
fakeRequest.Header.Add("Scope", "test")

Sanity Test

I expect, of course, that fakeRequest.Header != fakeRequestNoHeaders.Header. I write that test:

t.Run("HeadersSanityTest", func(t *testing.T) {


    assert.NotEqualf(t,
        fakeRequest.Header,
        fakeRequestNoHeaders.Header,
        "fakeRequest,fakeRequestNoHeaders share the same header state")

Result of test

It fails.

Why is this and how can I achieve what I'm trying?

UPDATE: I found the culprit:

the underlying http.Request, returned by httptest.NewRequest, is actually a pointer. Header simply belongs to that Request. The problem now reduces down to "How to deep-copy that Request."

mohan08p
  • 5,002
  • 1
  • 28
  • 36
Mike Warren
  • 3,796
  • 5
  • 47
  • 99
  • I found the culprit: the underlying `http.Request` passed in. It's a pointer, and that same pointer is being assigned to the fields of both fakeRequests. idk how to remedy this by deep-copy. – Mike Warren Sep 11 '18 at 13:50
  • I don't think there is a simple way to do a deep-copy. But you could try dereferencing both pointers when copying the request for a start (take a look at [this question](https://stackoverflow.com/questions/21011023/copy-pointer-values-a-b-in-golang)). This will at least create a new `http.Request`. But fields like the request's `Body` require special handling and I am not sure which other fields would require additional attention. Maybe take a look at [this discussion](https://groups.google.com/forum/#!msg/golang-nuts/ICMa3bQBUkM/lKxI4xuXXt0J) on the topic in the golang-nuts group. – Leon Sep 11 '18 at 14:03

1 Answers1

0

The issue was, indeed, not with the Header field, but instead the Request field, which was a pointer. (Oh no! I accidentally shallow-copied)

The Solution

I recalled, in one of my earlier tests, a method that I wrote specifically to get around this:

func makeBasicRequest() *web.Request {
    baseReq := httptest.NewRequest(http.MethodPost,
        "[some url here]",
        nil)
    req := new(web.Request)
    req.Request = baseReq
    return req
}

I basically just brought it into this test, and used it, hitting it once per fake request that I needed.

Mike Warren
  • 3,796
  • 5
  • 47
  • 99