Coder Social home page Coder Social logo

httpmock's Introduction

httpmock Build Status Coverage Status GoDoc Version Mentioned in Awesome Go

Easy mocking of http responses from external resources.

Install

Currently supports Go 1.13 to 1.23 and is regularly tested against tip.

v1 branch has to be used instead of master.

In your go files, simply use:

import "github.com/jarcoal/httpmock"

Then next go mod tidy or go test invocation will automatically populate your go.mod with the latest httpmock release, now Version.

Usage

Simple Example:

func TestFetchArticles(t *testing.T) {
  httpmock.Activate()
  defer httpmock.DeactivateAndReset()

  // Exact URL match
  httpmock.RegisterResponder("GET", "https://api.mybiz.com/articles",
    httpmock.NewStringResponder(200, `[{"id": 1, "name": "My Great Article"}]`))

  // Regexp match (could use httpmock.RegisterRegexpResponder instead)
  httpmock.RegisterResponder("GET", `=~^https://api\.mybiz\.com/articles/id/\d+\z`,
    httpmock.NewStringResponder(200, `{"id": 1, "name": "My Great Article"}`))

  // do stuff that makes a request to articles
  ...

  // get count info
  httpmock.GetTotalCallCount()

  // get the amount of calls for the registered responder
  info := httpmock.GetCallCountInfo()
  info["GET https://api.mybiz.com/articles"] // number of GET calls made to https://api.mybiz.com/articles
  info["GET https://api.mybiz.com/articles/id/12"] // number of GET calls made to https://api.mybiz.com/articles/id/12
  info[`GET =~^https://api\.mybiz\.com/articles/id/\d+\z`] // number of GET calls made to https://api.mybiz.com/articles/id/<any-number>
}

Advanced Example:

func TestFetchArticles(t *testing.T) {
  httpmock.Activate()
  defer httpmock.DeactivateAndReset()

  // our database of articles
  articles := make([]map[string]interface{}, 0)

  // mock to list out the articles
  httpmock.RegisterResponder("GET", "https://api.mybiz.com/articles",
    func(req *http.Request) (*http.Response, error) {
      resp, err := httpmock.NewJsonResponse(200, articles)
      if err != nil {
        return httpmock.NewStringResponse(500, ""), nil
      }
      return resp, nil
    })

  // return an article related to the request with the help of regexp submatch (\d+)
  httpmock.RegisterResponder("GET", `=~^https://api\.mybiz\.com/articles/id/(\d+)\z`,
    func(req *http.Request) (*http.Response, error) {
      // Get ID from request
      id := httpmock.MustGetSubmatchAsUint(req, 1) // 1=first regexp submatch
      return httpmock.NewJsonResponse(200, map[string]interface{}{
        "id":   id,
        "name": "My Great Article",
      })
    })

  // mock to add a new article
  httpmock.RegisterResponder("POST", "https://api.mybiz.com/articles",
    func(req *http.Request) (*http.Response, error) {
      article := make(map[string]interface{})
      if err := json.NewDecoder(req.Body).Decode(&article); err != nil {
        return httpmock.NewStringResponse(400, ""), nil
      }

      articles = append(articles, article)

      resp, err := httpmock.NewJsonResponse(200, article)
      if err != nil {
        return httpmock.NewStringResponse(500, ""), nil
      }
      return resp, nil
    })

  // mock to add a specific article, send a Bad Request response
  // when the request body contains `"type":"toy"`
  httpmock.RegisterMatcherResponder("POST", "https://api.mybiz.com/articles",
    httpmock.BodyContainsString(`"type":"toy"`),
    httpmock.NewStringResponder(400, `{"reason":"Invalid article type"}`))

  // do stuff that adds and checks articles
}

Algorithm

When GET http://example.tld/some/path?b=12&a=foo&a=bar request is caught, all standard responders are checked against the following URL or paths, the first match stops the search:

  1. http://example.tld/some/path?b=12&a=foo&a=bar (original URL)
  2. http://example.tld/some/path?a=bar&a=foo&b=12 (sorted query params)
  3. http://example.tld/some/path (without query params)
  4. /some/path?b=12&a=foo&a=bar (original URL without scheme and host)
  5. /some/path?a=bar&a=foo&b=12 (same, but sorted query params)
  6. /some/path (path only)

If no standard responder matched, the regexp responders are checked, in the same order, the first match stops the search.

go-testdeep + tdsuite example:

// article_test.go

import (
  "testing"

  "github.com/jarcoal/httpmock"
  "github.com/maxatome/go-testdeep/helpers/tdsuite"
  "github.com/maxatome/go-testdeep/td"
)

type MySuite struct{}

func (s *MySuite) Setup(t *td.T) error {
  // block all HTTP requests
  httpmock.Activate()
  return nil
}

func (s *MySuite) PostTest(t *td.T, testName string) error {
  // remove any mocks after each test
  httpmock.Reset()
  return nil
}

func (s *MySuite) Destroy(t *td.T) error {
  httpmock.DeactivateAndReset()
  return nil
}

func TestMySuite(t *testing.T) {
  tdsuite.Run(t, &MySuite{})
}

func (s *MySuite) TestArticles(assert, require *td.T) {
  httpmock.RegisterResponder("GET", "https://api.mybiz.com/articles.json",
    httpmock.NewStringResponder(200, `[{"id": 1, "name": "My Great Article"}]`))

  // do stuff that makes a request to articles.json
}

Ginkgo example:

// article_suite_test.go

import (
  // ...
  "github.com/jarcoal/httpmock"
)
// ...
var _ = BeforeSuite(func() {
  // block all HTTP requests
  httpmock.Activate()
})

var _ = BeforeEach(func() {
  // remove any mocks
  httpmock.Reset()
})

var _ = AfterSuite(func() {
  httpmock.DeactivateAndReset()
})


// article_test.go

import (
  // ...
  "github.com/jarcoal/httpmock"
)

var _ = Describe("Articles", func() {
  It("returns a list of articles", func() {
    httpmock.RegisterResponder("GET", "https://api.mybiz.com/articles.json",
      httpmock.NewStringResponder(200, `[{"id": 1, "name": "My Great Article"}]`))

    // do stuff that makes a request to articles.json
  })
})

Ginkgo + Resty Example:

// article_suite_test.go

import (
  // ...
  "github.com/jarcoal/httpmock"
  "github.com/go-resty/resty"
)
// ...
var _ = BeforeSuite(func() {
  // block all HTTP requests
  httpmock.ActivateNonDefault(resty.DefaultClient.GetClient())
})

var _ = BeforeEach(func() {
  // remove any mocks
  httpmock.Reset()
})

var _ = AfterSuite(func() {
  httpmock.DeactivateAndReset()
})


// article_test.go

import (
  // ...
  "github.com/jarcoal/httpmock"
  "github.com/go-resty/resty"
)

var _ = Describe("Articles", func() {
  It("returns a list of articles", func() {
    fixture := `{"status":{"message": "Your message", "code": 200}}`
    responder := httpmock.NewStringResponder(200, fixture)
    fakeUrl := "https://api.mybiz.com/articles.json"
    httpmock.RegisterResponder("GET", fakeUrl, responder)

    // fetch the article into struct
    articleObject := &models.Article{}
    _, err := resty.R().SetResult(articleObject).Get(fakeUrl)

    // do stuff with the article object ...
  })
})

httpmock's People

Contributors

afeld avatar battlecook avatar dlebech avatar gliptak avatar ikala-browny avatar jarcoal avatar kilianpaquier avatar konalegi avatar maxatome avatar nfnitloop avatar pires avatar pocke avatar pomyk avatar ranabram avatar roboslone avatar snigle avatar swithek avatar tarotaro0 avatar teepark avatar timkaye11 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

httpmock's Issues

getting no responder found error when using `Execute` method from `github.com/go-resty/resty/v2`

I am using resty v2 along with httpmock

github.com/go-resty/resty/v2 v2.3.0
github.com/jarcoal/httpmock v1.0.6

here is the test that can repro the error I am getting

package main

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/go-resty/resty/v2"
	"github.com/jarcoal/httpmock"
)

type fetchReq struct {
	URL         string
	Method      string
	Body        string
	QueryParams map[string]string
	Headers     map[string]string
}

func fetch(req *fetchReq, client *resty.Client) (*resty.Response, error) {
	method := req.Method
	if method == "" {
		method = "get"
	}
	request := client.R().
		SetHeader("content-type", "application/json").
		SetAuthToken("asdf").
		SetQueryParams(req.QueryParams).
		SetHeaders(req.Headers)

	if req.Body != "" {
		request.SetBody(req.Body)
	}

	// Make GET request
	resp, err := request.Execute(method, req.URL)
	return resp, err
}

func Test_fetch(t *testing.T) {
	type args struct {
		req *fetchReq
	}
	type mocker struct {
		method    string
		url       string
		responder httpmock.Responder
	}
	tests := []struct {
		name    string
		args    args
		want    []byte
		want1   *resty.Response
		wantErr bool
		m       []mocker
	}{
		{
			name: "TestSomething",
			args: args{
				req: &fetchReq{
					URL:    "https://example.com/events",
					Method: "get",
				},
			},
			want:    []byte{},
			wantErr: false,
			m: []mocker{
				{
					method:    "GET",
					responder: httpmock.NewStringResponder(500, `{"stat": "500"}`),
					url:       "https://example.com/events",
				},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			client := resty.New()
			// Get the underlying HTTP Client and set it to Mock
			httpmock.ActivateNonDefault(client.GetClient())
			defer httpmock.DeactivateAndReset()
			for i := range tt.m {
				httpmock.RegisterResponder(tt.m[i].method, tt.m[i].url, tt.m[i].responder)
			}

			got, err := fetch(tt.args.req, client)
			fmt.Println(httpmock.GetCallCountInfo())
			if (err != nil) != tt.wantErr {
				t.Errorf("fetch() error = %v, wantErr %v", err, tt.wantErr)
				return
			}
			if !reflect.DeepEqual(got, tt.want) {
				t.Errorf("fetch() got = %v, want %v", got, tt.want)
			}
		})
	}
}

In the above test I am registering responder for https://example.com/events but when I execute the test I get the following error

error = get "https://example.com/events": no responder found

my guess is that when I use the .Execute method something goes wrong, if I do not use the Execute method and modify fetch function to something like this I do not get any errors

resp, err := client.R().
		SetHeader("content-type", "application/json").
		SetAuthToken("asdf").
		SetQueryParams(req.QueryParams).
		SetHeaders(req.Headers).Get(req.URL)

It could be an resty issue too, happy to open an issue in the resty repo.

url parameters

I would implement a mock for our api but there is a huge amount url params what I also have to implement/mock in this case:

httpmock.RegisterResponder("GET", "https://domain/partners/cases/1234",
	...
)

So the 1234 should be a place where I can get the id of the resource.

httpmock.RegisterResponder("GET", "https://domain/partners/cases/{id}",
	...
)

Is there any chance to have it working somehow?

Failed to run tests in parallel with Ginkgo

DEMO

package main

import (
	"log"
	"net/http"
	"os"
	"testing"

	"github.com/jarcoal/httpmock"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = BeforeSuite(func() {
	httpmock.Activate()
})

var _ = BeforeEach(func() {
	httpmock.Reset()
})

var _ = AfterSuite(func() {
	httpmock.DeactivateAndReset()
})

var _ = Describe("Articles", func() {
	It("case a", func() {
		httpmock.RegisterResponder("GET", "https://1.com",
			httpmock.NewStringResponder(200, ""))

		resp, err := http.Get("https://1.com")
		Expect(err).Should(BeNil())
		Expect(resp.StatusCode).To(Equal(200))

		log.Println(os.Getpid())
	})

	It("case b", func() {
		httpmock.RegisterResponder("GET", "https://2.com",
			httpmock.NewStringResponder(200, ""))

		resp, err := http.Get("https://2.com")
		Expect(err).Should(BeNil())
		Expect(resp.StatusCode).To(Equal(200))

		log.Println(os.Getpid())
	})
})

func TestParallel(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Test Suite")
}

Exec

ginkgo -nodes=2

Result

Running Suite: Test Suite
=========================
Random Seed: 1589013597
Will run 2 specs

Running in parallel across 2 nodes

failed to iterate over tests:
Get "http://127.0.0.1:53853/counter": no responder found


failed to iterate over tests:
Get "http://127.0.0.1:53853/counter": no responder found


Ran 0 of 0 Specs in 0.002 seconds
FAIL! -- 0 Passed | 0 Failed | 0 Pending | 0 Skipped


Ginkgo ran 1 suite in 3.272456673s
Test Suite Failed

Allow some http request

As far I know, httpmock.Activate() will block all http request that go out from the project.
Can you make a method for allowing some http request?

Is there a way to mock a non-responding http server

Kinda counter-inituative, but I'm building a service that relies on getting an IP from the ec2-metadata endpoint trouble is that endpoint is only available when within AWS.

I have some logic that will branch, if you aren't in an AWS environment. However, I could write a unit that just calls the endpoint and watch it fail, but I feel as so there are side-effects (My unit test is probably running in AWS :P). Is there someway I can mock a non-responding server? i.e non-routable?

Status of this project

It looks like this project is not getting any attention lately. Since it's still number one result on Google for http mocking in golang (at least for me), I feel it would be a shame if it dies.

To anyone else that read this issue: I have tried to reach out directly to Jared to see if we can revive this project and take a look at the current open PRs. I will be happy to help with bringing this project forward if necessary.

On a different note, the library works for me as-is, and I don't necessarily feel like it has to grow to huge proportions. But at least some faster responsiveness on issues and pull requests would be greatly appreciated, and I hope that the community would agree with me on this.

Cheers :-)

MockTransport ignores request.Cancel

This is the mechanism that gets used to implement client timeouts, so httpmock ends up clobbering timeouts.

client := &http.Client{
    Timeout: 5 * time.Millisecond,
}

httpmock.ActivateNonDefault(client)
defer httpmock.DeactivateAndReset()

httpmock.RegisterResponder(
    "GET", "http://example.com/",
    func(r *http.Request) (*http.Response, error) {
        time.Sleep(10 * time.Millisecond)
        return httpmock.NewStringResponse(http.StatusOK, ""), nil
    },
)

response, err := client.Get("http://example.com")
// err is nil, and timing the `client.Get` verifies that it takes > 10ms

Registering more than 5 responders

Hi all,

I have been running into indeterministic behavior while setting up multiple responders for a single test. To give you more context, the handler I am testing actually makes external request to 6 different endpoints, gathers the result. Here's the test code:

func TestEndpoint(t *testing.T) {

	httpmock.Activate()
	defer httpmock.DeactivateAndReset()

	fakeResponseJsonA := []byte(`{"result": "fake-result"}`)
	url := fmt.Sprintf("%s/fakeA", os.Getenv("FAKE_A"))
	httpmock.RegisterResponder(http.MethodPost, url, httpmock.NewBytesResponder(http.StatusOK, fakeA))

	
  fakeResponseJsonB:= []byte(`{"result": "fake-result"}`)
	url := fmt.Sprintf("%s/fakeB", os.Getenv("FAKE_B"))
	httpmock.RegisterResponder(http.MethodPost, url, httpmock.NewBytesResponder(http.StatusOK, fakeB))

...

Changing the order of the httpmock.RegisterResponder calls result in no responder found errors. In the past I was able to make this work for 4 calls in a test but it looks like I am hitting an edge case. Any ideas why this might be happening?

Using Go1.11.4 with GorillaMux with httpmock.v1

Httpmock not working with resty

Hi,
I am using httpmock with resty, I don't want to mock all the URLs, but it is not mocking the registered URLs.
Here , is a code snippet for your reference

_restyClient = resty.New()
defer httpmock.DeactivateAndReset()
httpmock.ActivateNonDefault(_restyClient.GetClient())
httpmock.RegisterNoResponder(httpmock.InitialTransport.RoundTrip)

httpmock.RegisterResponder(http.MethodPost, url,
		func(req *http.Request) (*http.Response, error) {
			resp, err := httpmock.NewJsonResponse(http.StatusOK, `{
			"username" : "pooja",
			"password" : "jfghoeiwoivlcvkljg"

			}`)
			if err != nil {
				return httpmock.NewJsonResponse(http.StatusInternalServerError, `{"error": "Invalid response from server"}`)

			}
			return resp, nil
		},
)

_resp, _err := _restyClient.R().
SetHeader("content-type", "application/json").
SetBody(bytes.NewBuffer([]byte(`{"description":"test"}`))).
Post("http://localhost:3000/api/v1/accounts/fgkjgkfjg/"))
assert.Equal(t, 2, httpmock.GetTotalCallCount())

Assertions on request bodies?

It would be convenient to have a way to add code to the mock that checks the request and asserts on it. Would you consider patches in this direction?

Query param encoding issue

There remains in #54 an issue with encoding of query parameters. Easy to repro by adding testUrlPath + "?a=b%3Dc" as a test url in TestRegisterResponderWithQuery. When using RegisterResponderWithQuery, the responder URL uses an unescaped query string (a=b=c), whereas the http request uses the original escaped query string.

I believe that #55 would fix this but haven't tried. I would submit a fix but I believe #55 is a better way to go.

how httpmock works with InsecureSkipVerify

I am using httpmock test my function, in my function, I have a line as follow:
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
And when I run my test, there is an error shows:

panic: interface conversion: http.RoundTripper is *httpmock.MockTransport, not *http.Transport

If I remove this line , the test runs normally. But I need this line of code. Could you help on this ?

Mock not working

I have my http client using transport : [ client := &http.Client{Transport: tr} ]. When I do a mock on this, it fails. Whereas if I remove the transport [ client := &http.Client{} ], it works. Could you please explain a solution to this issue ?

Query paramter with no value

Recent change #50 in the v1 branch breaks the behavior of query parameter without values. Query parameter with no value is valid due to RFC 3986.
Here's a patch to test the case.

--- a/transport_test.go
+++ b/transport_test.go
@@ -217,6 +217,9 @@ func TestMockTransportPathOnlyFallback(t *testing.T) {
 		"/hello/world?query=string&query=string2": {
 			testUrl + "hello/world?query=string&query=string2",
 		},
+		"/hello/world?query": {
+			testUrl + "hello/world?query",
+		},
 		"/hello/world#fragment": {
 			testUrl + "hello/world#fragment",
 		},

Ping to the related patch authors: @konalegi (for #50), @Zanadar (for #55) and @maxatome (for #61)

Default/Zero-Value Request.Method not respected

The documentation for Request.Method says: "For client requests an empty string means GET".

But in transport.go, the bare Request.Method gets used, without defaulting to "GET" if the Method is "". This means that if RoundTrip receives an http.Request which has a zero-value .Method, it can't properly look up any GET responders for that request.

The error message from http is a bit misleading:

Get https://my.example.com/endpoint?my_var=my_value: no responder found, makes it look like httpmock doesn't support matching URLs with parameters. Thankfully, after reading the source, I found that it does. (yay!) :)

NewGZipResponder

Some API's return GZip compressed responses. This would be a really useful feature to support.

Support for go 1.17

Hi all,

Will 1.17 be also supported? Not really sure what needs to be changed/added? I would issue a PR but, is it just adding a line in travis conf?

Thanks

[Question] How to add custom values in the response header ?

Hi,

I'd like to mock an API call that return the count of total lines in a value put in the response header.
The API has parameters to indicate the page et the number of expected result per page. The response contains the number of total result lines, so it's possible to know how many call to do with the right page number.

I'm looking for the best way to do it with this httpmock package.
Is that doable ?
what would be the best way to do it.
Best regards
Steeve

Race condition due to ResponderFromResponse() copying Body object

I came across this when parallelizing some backend HTTP calls.

The short of it is that NewStringResponder(), NewBytesResponder(), etc... are all subject to racing since ResponderFromResponse() will create new http.Response objects use the same underlying Body object in each response.

My assumption would be that supplying a string in NewStringResponder() would be free of races. If so - I believe a possible fix is to inline ResponderFromResponse() into each method and ensure NewRespBodyFromString() or NewRespBodyFromBytes() is called for each new http.Response object created.

Data Race Issue

Let me start by saying, this might be entirely my fault, and I barely understand anything about Go.

I'm attempting to convert a test from using a pretty ugly chunk of httptest code to httpmock:

dropbox/changes-client@handle-abortions...httpmock

However, upon doing this we hit a race which only presents itself with httpmock:

==================
WARNING: DATA RACE
Write by goroutine 7:
  github.com/jarcoal/httpmock.Deactivate()
      /home/vagrant/src/github.com/jarcoal/httpmock/transport.go:139 +0x51
  github.com/jarcoal/httpmock.DeactivateAndReset()
      /home/vagrant/src/github.com/jarcoal/httpmock/transport.go:150 +0x2b
  github.com/dropbox/changes-client/engine.TestCompleteFlow()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine_test.go:296 +0x1b4c
  testing.tRunner()
      /usr/local/go/src/pkg/testing/testing.go:422 +0x10f

Previous read by goroutine 11:
  net/http.(*Client).send()
      /usr/local/go/src/pkg/net/http/client.go:118 +0x39e
  net/http.(*Client).doFollowingRedirects()
      /usr/local/go/src/pkg/net/http/client.go:343 +0xd31
  net/http.(*Client).Get()
      /usr/local/go/src/pkg/net/http/client.go:275 +0xcd
  net/http.Get()
      /usr/local/go/src/pkg/net/http/client.go:252 +0x6e
  github.com/dropbox/changes-client/engine.(*UpstreamMonitor).fetchJobStep()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/upstream_monitor.go:55 +0x151
  github.com/dropbox/changes-client/engine.(*UpstreamMonitor).WaitUntilAbort()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/upstream_monitor.go:33 +0x6c
  github.com/dropbox/changes-client/engine.funcยท005()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine.go:213 +0x95

Goroutine 7 (running) created at:
  testing.RunTests()
      /usr/local/go/src/pkg/testing/testing.go:504 +0xb46
  testing.Main()
      /usr/local/go/src/pkg/testing/testing.go:435 +0xa2
  main.main()
      github.com/dropbox/changes-client/engine/_test/_testmain.go:47 +0xdc

Goroutine 11 (running) created at:
  github.com/dropbox/changes-client/engine.(*Engine).runBuildPlan()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine.go:217 +0x8c9
  github.com/dropbox/changes-client/engine.(*Engine).Run()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine.go:75 +0x1e5
  github.com/dropbox/changes-client/engine.RunBuildPlan()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine.go:59 +0x1a8
  github.com/dropbox/changes-client/engine.TestCompleteFlow()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine_test.go:196 +0xb7b
  testing.tRunner()
      /usr/local/go/src/pkg/testing/testing.go:422 +0x10f
==================
==================
WARNING: DATA RACE
Write by goroutine 7:
  github.com/jarcoal/httpmock.Reset()
      /home/vagrant/src/github.com/jarcoal/httpmock/transport.go:144 +0x4e
  github.com/jarcoal/httpmock.DeactivateAndReset()
      /home/vagrant/src/github.com/jarcoal/httpmock/transport.go:151 +0x30
  github.com/dropbox/changes-client/engine.TestCompleteFlow()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine_test.go:296 +0x1b4c
  testing.tRunner()
      /usr/local/go/src/pkg/testing/testing.go:422 +0x10f

Previous read by goroutine 11:
  github.com/jarcoal/httpmock.(*MockTransport).responderForKey()
      /home/vagrant/src/github.com/jarcoal/httpmock/transport.go:63 +0x43
  github.com/jarcoal/httpmock.(*MockTransport).RoundTrip()
      /home/vagrant/src/github.com/jarcoal/httpmock/transport.go:41 +0x10e
  net/http.send()
      /usr/local/go/src/pkg/net/http/client.go:195 +0x62d
  net/http.(*Client).send()
      /usr/local/go/src/pkg/net/http/client.go:118 +0x200
  net/http.(*Client).doFollowingRedirects()
      /usr/local/go/src/pkg/net/http/client.go:343 +0xd31
  net/http.(*Client).Get()
      /usr/local/go/src/pkg/net/http/client.go:275 +0xcd
  net/http.Get()
      /usr/local/go/src/pkg/net/http/client.go:252 +0x6e
  github.com/dropbox/changes-client/engine.(*UpstreamMonitor).fetchJobStep()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/upstream_monitor.go:55 +0x151
  github.com/dropbox/changes-client/engine.(*UpstreamMonitor).WaitUntilAbort()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/upstream_monitor.go:33 +0x6c
  github.com/dropbox/changes-client/engine.funcยท005()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine.go:213 +0x95

Goroutine 7 (running) created at:
  testing.RunTests()
      /usr/local/go/src/pkg/testing/testing.go:504 +0xb46
  testing.Main()
      /usr/local/go/src/pkg/testing/testing.go:435 +0xa2
  main.main()
      github.com/dropbox/changes-client/engine/_test/_testmain.go:47 +0xdc

Goroutine 11 (running) created at:
  github.com/dropbox/changes-client/engine.(*Engine).runBuildPlan()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine.go:217 +0x8c9
  github.com/dropbox/changes-client/engine.(*Engine).Run()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine.go:75 +0x1e5
  github.com/dropbox/changes-client/engine.RunBuildPlan()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine.go:59 +0x1a8
  github.com/dropbox/changes-client/engine.TestCompleteFlow()
      /home/vagrant/src/github.com/dropbox/changes-client/engine/engine_test.go:196 +0xb7b
  testing.tRunner()
      /usr/local/go/src/pkg/testing/testing.go:422 +0x10f
==================

test httpstatus 302 on resty OnAfterResponse not expected

I want use resty OnAfterResponse interface disable 302 auto redirect and replace with my own error.
when i tested this goal, then return "no responder found"

import (
	"errors"
	"fmt"
	"github.com/go-resty/resty/v2"
	"github.com/jarcoal/httpmock"
	"github.com/stretchr/testify/assert"
	"net/http"
	"strings"
	"testing"
	"time"
)

var ErrNoAuth = errors.New("no auth")

func createClient() *resty.Client {
	client := resty.New()
	client.EnableTrace()
	client.SetTimeout(time.Second * 60)
	client.SetRetryCount(0)
	client.SetBaseURL("http://mock.server")

	client.OnAfterResponse(func(client *resty.Client, response *resty.Response) error {
		switch response.StatusCode() {
		case http.StatusFound:
			location := response.Header().Get("Location")
			if strings.Contains(location, "/account/login") {
				fmt.Printf("matched 302 location. return ErrNoAuth\n")
				return ErrNoAuth
			}
		}
		return nil
	})

	return client
}

func TestForResty302(t *testing.T) {
	client := createClient()

	httpmock.Activate()
	httpmock.ActivateNonDefault(client.GetClient())
	defer httpmock.DeactivateAndReset()

	httpmock.RegisterResponder("POST", "/api/v1/some_action", func(request *http.Request) (*http.Response, error) {
		response := httpmock.NewStringResponse(http.StatusFound, "")
		response.Header.Set("Location", "https://new.server/account/login")
		return response, nil
	})

	post, err := client.R().Post("/api/v1/some_action")
	_ = post
	_ = err
	// Output: Post "https://new.server/account/login": no responder found
	fmt.Printf("%+v\n", err)

	// Expect
	assert.ErrorIs(t, err, ErrNoAuth)
}

Implemented test case with mock. but it's not working

I implemented a code to get data from the API. And also wrote the test case with mock to that method by using https://github.com/jarcoal/httpmock. But mocking was not executing. Getting original data from the data. not getting mock data. tried in all the ways. but not working. can anyone help me please?

func MakeAPIRequest(url string) ([]byte, error) {
    req, err := http.NewRequest(http.MethodGet, url, nil)
    if err != nil {
        log.Fatal(err)
    }
    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    httpClient := &http.Client{Transport: tr}
    response, err := httpClient.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    defer response.Body.Close()
    body, err := ioutil.ReadAll(response.Body)
    if err != nil {
        log.Fatal(err)
    }
    return body, nil
}

Test case code Is

func TestMakeAPIRequest(t *testing.T) {
    httpmock.Activate()
    defer httpmock.DeactivateAndReset()
    httpmock.RegisterResponder("GET", "https://jsonplaceholder.typicode.com/users/1",
        httpmock.NewStringResponder(200, `{
            "id": 1,
            "name": "Leanne Graham Test Name",
            "username": "Bret",
            "email": "[email protected]",
            "address": {
              "street": "Kulas Light",
              "suite": "Apt. 556",
              "city": "Gwenborough",
              "zipcode": "92998-3874",
              "geo": {
                "lat": "-37.3159",
                "lng": "81.1496"
              }
            },
            "phone": "1-770-736-8031 x56442",
            "website": "hildegard.org",
            "company": {
              "name": "Romaguera-Crona",
              "catchPhrase": "Multi-layered client-server neural-net",
              "bs": "harness real-time e-markets"
            }
          }`))

    data, err := MakeAPIRequest("https://jsonplaceholder.typicode.com/users/1")
    fmt.Println("data:", string(data), err)
    fmt.Println(httpmock.GetCallCountInfo())
}

getting 0 when call
fmt.Println(httpmock.GetCallCountInfo())

https://stackoverflow.com/questions/64769575/implemented-test-case-with-mock-but-its-not-working

Watchout for custom implementation of http.Transport!

If your package implements your own http.Transport (for example, to bypass tls cert verification), it will not allow httpmock to intercept requests as it depends on your http.Client using the default http.DefaultTransport. Would be nice if this warning was in the readme.

No responder found when mocking with Cobra.Execute()

Hi, I am trying to mock requests that are being made by some cobra commands in our CLI.
But I end up encountering this error
Get \"http://localhost:9081/api/user/performance/profiles?page_size=25&search=test\": no responder found

Here is the implementation:-

func TestPerfView(t *testing.T) {
	// setup current context
	utils.SetupContextEnv(t)

	// initialize mock server for handling requests
	utils.StartMockery(t)

	// create a test helper
	testContext := utils.NewTestHelper(t)

	// get current directory
	_, filename, _, ok := runtime.Caller(0)
	if !ok {
		t.Fatal("problems recovering caller information")
	}
	currDir := filepath.Dir(filename)
	fixturesDir := filepath.Join(currDir, "fixtures")

	// test scenrios for fetching data
	tests := []struct {
		Name             string
		Args             []string
		View             string
		ExpectedResponse string
		Fixture          string
		URL              string
		Token            string
		ExpectError      bool
	}{
		{
			Name:             "View Profiles",
			Args:             []string{"view", "test", "--token", filepath.Join(fixturesDir, "token.golden")},
			View:             "Profiles",
			ExpectedResponse: "view.profile.output.golden",
			Fixture:          "view.profile.api.response.golden",
			URL:              testContext.BaseURL + "/api/user/performance/profiles?search=test",
			Token:            filepath.Join(fixturesDir, "token.golden"),
			ExpectError:      false,
		},
	}

	// Run tests
	for _, tt := range tests {
		t.Run(tt.Name, func(t *testing.T) {
			// View api response from golden files
			apiResponse := utils.NewGoldenFile(t, tt.Fixture, fixturesDir).Load()

			// set token
			tokenPath = tt.Token

			// mock response
			httpmock.RegisterResponder("GET", tt.URL,
				httpmock.NewStringResponder(200, apiResponse))

			// Expected response
			testdataDir := filepath.Join(currDir, "testdata")
			golden := utils.NewGoldenFile(t, tt.ExpectedResponse, testdataDir)

			// Grab outputs from console.
			var buf bytes.Buffer
			log.SetOutput(&buf)
			utils.SetupLogrusFormatter()

			PerfCmd.SetArgs(tt.Args)
			PerfCmd.SetOutput(&buf)
			err := PerfCmd.Execute()
			if err != nil {
				// if we're supposed to get an error
				if tt.ExpectError {
					// write it in file
					if *update {
						golden.Write(err.Error())
					}
					expectedResponse := golden.Load()

					utils.Equals(t, expectedResponse, err)
					return
				} else {
					t.Error(err)
				}
			}

			// response being printed in console
			actualResponse := buf.String()

			// write it in file
			if *update {
				golden.Write(actualResponse)
			}
			expectedResponse := golden.Load()

			utils.Equals(t, expectedResponse, actualResponse)
		})
	}

	// stop mock server
	utils.StopMockery(t)
}

No respond for URL question

I am using httpmock for testing my REST client recently.

The version of httpmock is github.com/jarcoal/httpmock v1.0.8

I have a piece of test code, it looks not that complicated, but it always panic 2021/12/16 22:17:24 Response err:Get "https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123": no responder found

The test code is like below:

func TestGetResources(t *testing.T) {
	httpmock.Activate()
	defer httpmock.DeactivateAndReset()

	host := "test.com"
	path := "/ltm/test_resources/"
	username := "admin"
	password := "password"
	inscure := true

	se := InitSession(host, username, password, inscure)
	se.Client = &http.Client{}
	serv := Service{
		Path:    path,
		Session: se,
	}
	partition := "Project_test123"
	// url := "https://" + host + serv.URIForPartition(partition)
	// url := `https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123` (not work)
	url := "https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123"
	// url := "/ltm/test_resources" (not work)

	resp := []byte("hello")

        // I register a byte responder for
        // URL  "https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123"
	httpmock.RegisterResponder(
		"GET", url, httpmock.NewBytesResponder(200, resp),
	)

	body := serv.GetResources(partition)

	assert.Equal(t, *body, resp)

}

when I run the test, it always returns panic:

=== RUN   TestGetResources
2021/12/16 22:17:24 Get Reousrces
2021/12/16 22:17:24 Request URL is: https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123
2021/12/16 22:17:24 Response err:Get "https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123": no responder found
--- FAIL: TestGetResources (0.00s)
panic: Repsonse err:Get "https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123": no responder found [recovered]
        panic: Repsonse err:Get "https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123": no responder found

As you can see I log the Request URL is: https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123, it is the same as I registered for the Responder.

Request URL is: https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123
        url := "https://test.com/ltm/test_resources/?$filter=partition%20eq%20Project_test123"

I referred to this issue #106 to try to use /ltm/test_resources to match any path with it. it does not work either.

Inconsist behavior between http.Response.Body and httpmock.Response.Body

httpmock.RegisterResponder("GET", "http://127.0.0.1:12350/test_01",
	httpmock.NewStringResponder(200, "test"))
httpmock.Activate()

body, _ := http.Get("http://127.0.0.1:12350/test_01")
bytes, _ := ioutil.ReadAll(body.Body)
fmt.Println(string(bytes))

bytes2, _ := ioutil.ReadAll(body.Body)
fmt.Println(string(bytes2))

httpmock.Deactivate()

This will print test twice, but use a real server it will only print once since you can't read twice from a http.Body.

Issue while using ActivateNonDefault

I'm using ActivateNonDefault for activating the mocks on my custom client but I see it not intercepting the calls. My client is using http.DefaultTransport for transport which I'm passing
client := &http.Client{Transport: http.DefaultTransport}
httpmock.ActivateNonDefault(client)
while activating the client.,I also tried passing the way it is in documentation which did not help me.,
Can someone help me.,Thanks in advance!

no matching versions for query "latest"

I'm struggling with deploying an app to Google AppEngine, and can't seem to find anyone with the same error online, so I'll document it here. The error is:

Error message: go: finding module for package gopkg.in/jarcoal/httpmock.v1
github.com/akfaew/xxx imports
        github.com/bold-commerce/go-shopify tested by
        github.com/bold-commerce/go-shopify.test imports
        gopkg.in/jarcoal/httpmock.v1: no matching versions for query "latest"

I'm not sure how to fix it yet.

t.Parallel()

at the moment table tests and two different tests are not able to be run in parallel mode (with t.Parallel()).
Any plans on fixing this?

Content-Type header is not set

By setting NewJsonResponder, It should include the proper header, same with string or a custom way to implement proper headers for mocks.

httmock not working with resty

I have this small code block to test resty + httpmock but the requests is not being intercepted.
I'm getting the google page html as a response.
Am I missing anything?

package main

import (
	"fmt"

	"github.com/go-resty/resty/v2"
	"github.com/jarcoal/httpmock"
)

func main() {
	client := resty.New()
	httpmock.ActivateNonDefault(resty.New().GetClient())
	defer httpmock.DeactivateAndReset()

	httpmock.RegisterResponder("GET", "https://google.com",
		httpmock.NewStringResponder(200, `[{"id": 1, "name": "My Great Article"}]`))

	resp, _ := client.R().
		Get("https://google.com")

	fmt.Println(resp)

}

Configuration request and response from JSON file

Hello.
Can support import request and response from JSON file configuration?
For example:

{
    "request": {
        "method": "GET",
        "url": "/test"
    },
    "response": {
        "status": 200,
        "body": "test 200 OK\n"
    }
}

Examples run

curl http://localhost/test
test 200 OK

http.Client can't send request to mocked server with non-default transport

It's a very weird question.

When I send request with http.Client{}, the mock server could receive the request.

But, when I send request with

``

c := http.Client{
   Transport: &http.Transport{
      Proxy: http.ProxyFromEnvironment,
      DialContext: (&net.Dialer{
         Timeout:   30 * time.Second,
         KeepAlive: 30 * time.Second,
         DualStack: true,
      }).DialContext,
      ForceAttemptHTTP2:     true,
      MaxIdleConns:          100,
      IdleConnTimeout:       90 * time.Second,
      TLSHandshakeTimeout:   10 * time.Second,
      ExpectContinueTimeout: 1 * time.Second,
   },
}

`
The mock server could not receive the request.

I just copy DefaultTransport and paste into http.Client

Here is the code below:

First, the successful code:

``

package main

import (
   "fmt"
   "github.com/jarcoal/httpmock"
   "io/ioutil"
   "net/http"
   "strings"
)

const URL = "https://abc.def.com/articles"

func main() {
   // mock server
   httpmock.Activate()
   defer httpmock.DeactivateAndReset()
   httpmock.RegisterResponder(http.MethodPost, URL,
      func(req *http.Request) (*http.Response, error) {
         fmt.Println("123456")
            return httpmock.NewStringResponse(200, "200"), nil
      },
   )

   // send http request
   err := PostHttpRequest(URL, "")
   fmt.Println(err)
}

// PostHttpRequest PostHttpRequest
func PostHttpRequest(urls, params string) error {
   c := http.Client{}
   r, err := c.Post(urls, "application-json", strings.NewReader(params))
   if err != nil {
      return err
   }
   defer r.Body.Close()
   resp, err := ioutil.ReadAll(r.Body)
   if err != nil {
      return err
   }
   fmt.Println(string(resp))
   return nil
}

Then, the failed code:

``

package main

import (
   "fmt"
   "github.com/jarcoal/httpmock"
   "io/ioutil"
   "net"
   "net/http"
   "strings"
   "time"
)

const URL = "https://abc.def.com/articles"

func main() {
   // mock server
   httpmock.Activate()
   defer httpmock.DeactivateAndReset()
   httpmock.RegisterResponder(http.MethodPost, URL,
      func(req *http.Request) (*http.Response, error) {
         fmt.Println("123456")
            return httpmock.NewStringResponse(200, "200"), nil
      },
   )

   // send http request
   err := PostHttpRequest(URL, "")
   fmt.Println(err)
}

// PostHttpRequest PostHttpRequest
func PostHttpRequest(urls, params string) error {
   c := http.Client{
      Transport: &http.Transport{
         Proxy: http.ProxyFromEnvironment,
         DialContext: (&net.Dialer{
            Timeout:   30 * time.Second,
            KeepAlive: 30 * time.Second,
            DualStack: true,
         }).DialContext,
         ForceAttemptHTTP2:     true,
         MaxIdleConns:          100,
         IdleConnTimeout:       90 * time.Second,
         TLSHandshakeTimeout:   10 * time.Second,
         ExpectContinueTimeout: 1 * time.Second,
      },
   }
   r, err := c.Post(urls, "application-json", strings.NewReader(params))
   if err != nil {
      return err
   }
   defer r.Body.Close()
   resp, err := ioutil.ReadAll(r.Body)
   if err != nil {
      return err
   }
   fmt.Println(string(resp))
   return nil
}

The error is: Post "https://abc.def.com/articles": dial tcp: lookup abc.def.com: no such host

Could you help the solve this? Thank you very much in advance! Any response will be highly appreciated!

golangcli-lint says no export data for "github.com/jarcoal/httpmock"

I am trying to run golangcli-lint, and got this:

WARN [runner] Can't run linter goanalysis_metalinter: deadcode: analysis skipped: errors in package: [/home/yann/worldr/github/server/vault_test.go:9:2: could not import github.com/jarcoal/httpmock (vault_test.go:9:2: cannot find package "." in:
        /home/yann/worldr/github/server/vendor/github.com/jarcoal/httpmock)]
WARN [runner] Can't run linter unused: buildir: failed to load package : could not load export data: no export data for "github.com/jarcoal/httpmock"
ERRO Running error: buildir: failed to load package : could not load export data: no export data for "github.com/jarcoal/httpmock"

Any idea how to fix that?

http mocks regardless of domain

Hey,

It looks like httpmock, mocks the HTTP transporter regardless of the domain that is being called.

func Test_mockHTTP(t *testing.T) {
	httpmock.Activate()

	// I only want to mock the https://some-domain.com
	httpmock.RegisterResponder(http.MethodGet, "https://some-domain.com", httpmock.NewStringResponder(http.StatusOK, "hello world"))

	client := http.Client{}

	// The request should get intercepted
	_, err := client.Get("https://some-domain.com")
	require.NoError(t, err)

	// The request should NOT get intercepted, but it does and fails with Get "https://sumup.com": no responder found
	_, err = client.Get("https://gitlab.com")
	require.NoError(t, err)
}

If this is not by design, I am happy to submit a PR

Context Timeout Ignored

Hello, thanks for your great lib, really helpful!

I recently hit a problem trying to test timeouts: when setting a timeout in a http.Client the request is properly canceled in case of timeout exceeded, but when setting a context.Context timeout the request is never canceled.

The following test is passing successfully:

import (
  "net/http"
  "testing"
  "time"

  "gopkg.in/jarcoal/httpmock.v1"
)

func TestTimeout(t *testing.T) {
	httpmock.Activate()
	defer httpmock.DeactivateAndReset()

	httpmock.RegisterResponder("POST", "https://example.com/",
		func(req *http.Request) (*http.Response, error) {
			resp, err := httpmock.NewJsonResponse(200, newResponse)
			if err != nil {
				return httpmock.NewStringResponse(400, ""), nil
			}
			time.Sleep(1000 * time.Millisecond)
			return resp, nil
		},
	)

	req, err := http.NewRequest("POST", "https://example.com/", nil)
	if err != nil {
		t.Fatal(err)
	}

	client := &http.Client{Timeout: 1 * time.Millisecond}
	_, err = client.Do(req)

       // Properly getting a timeout exceeded error so test is passing.
	if err == nil {
		t.Fatal("Want a timeout exceeded error but got none.")
	}
}

But the following is not:

import (
  "context"
  "net/http"
  "testing"
  "time"

  "gopkg.in/jarcoal/httpmock.v1"
)

func TestTimeout(t *testing.T) {
	httpmock.Activate()
	defer httpmock.DeactivateAndReset()

	httpmock.RegisterResponder("POST", "https://example.com/",
		func(req *http.Request) (*http.Response, error) {
			resp, err := httpmock.NewJsonResponse(200, newResponse)
			if err != nil {
				return httpmock.NewStringResponse(400, ""), nil
			}
			time.Sleep(1000 * time.Millisecond)
			return resp, nil
		},
	)

	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond)
	defer cancel()
	req, err := http.NewRequestWithContext(ctx, "POST", "https://example.com/", nil)
	if err != nil {
		t.Fatal(err)
	}

	client := &http.Client{}
	_, err = client.Do(req)

       // Not getting a timeout exceeded error so test is not passing.
	if err == nil {
		t.Fatal("Want a timeout exceeded error but got none.")
	}

Do you think I'm doing something wrong?
I don't have the problem with the std lib: https://golang.org/pkg/net/http/httptest

Thanks a lot!

Error Responder

Hi all guys!

I'm using your httpmock in a project, and I found it very clear and useful. I like it, and I will use it also in the future on other projects.

I'm using it to mock http.Client, and I need to mock an error responder.

There's a way to do in on the actual version? Or will be in future releases?

Cheers

Nested handler causing deadlock

I ran into an issue where I had mocked two servers and one of the handlers was called from within the another mocked handler. Not on purpose, but the test hung indefinitely. I found out it's because there is a mutex around the handler internally so this lead to a deadlock.

I'm sorry I don't have a code snippet because I had to do some major refactoring and ended up removing httpmock for my test to work around this issue. I wanted to add the issue here before I forgot.

Unable to emulate the http mock server

I followed the instructions given on the readme to setup a mock http server.
However when I run the test I always get host not found exception which is the result that my httpclient instead of connecting to the mock server is trying to connect to an actual server.

Please advice.

Great work by the way

Request do not propagate to package functions

I'm trying to mock a URL that a function requests at the package I'm testing and it still executes the request to the original URL instead of the mocked one that we defined.
Is there support for acessing mocked urls at package functions or only inside the test?

mockedResponse := map[string]interface{}{
        "data": []map[string]interface{}{
            map[string]interface{}{
                "key": "pipitchu",
            },
        },
        "message": nil,
        "success": true,
    }

        url := "https://test.pipitchu.com/123"
    httpmock.RegisterResponder("GET", url,
        func(req *http.Request) (*http.Response, error) {
            resp, err := httpmock.NewJsonResponse(200, mockedResponse)
            if err != nil {
                return httpmock.NewStringResponse(500, ""), nil
            }
            return resp, nil
        },
    )

key, err := GetKey(123456)
// key is the "key" key of the first element of the data array
assert(t, "pipitchu", key)
// we're using testify

Thanks in advance!

Default responder

Can I somehow create a default responder, which is handle all other incoming request?

The problem:
If I'm register a responder for a specific endpoint and if it has been changed in the code I get an panic usually, because if there isn't responder, so the http.Response will be empty.

Possible solution:
Create a function or something like that as the following:

httpmock.DefultResponder(
	func(req *http.Request) (*http.Response, error) {
		// do something
		return httpmock.NewStringResponse(500, ""), nil
	},
)

Use http status number with text code instead of just the status number as a string

Status: strconv.Itoa(status),

According to https://golang.org/src/net/http/response.go?s=731:4298#L25 the http Response object should return the http status number as well as the status text. So

&http.Response{
		Status:        strconv.Itoa(status),
		StatusCode:    status,
		Body:          NewRespBodyFromString(body),
		Header:        http.Header{},
		ContentLength: -1,
	}

should be

		Status:        strconv.Itoa(status) + " " + http.StatusText(status),
		StatusCode:    status,
		Body:          NewRespBodyFromString(body),
		Header:        http.Header{},
		ContentLength: -1,
	}

"go get" doesn't install import of httpmock?

When the Go code contains an import statement, e.g.

import {
...other packages....
"gopkg.in/jarcoal/httpmock.v1"
}

and then "go get" is used to install the imports from the whole codebase, the httpmock package is not installed and no error message is produced. All other imported packages are installed properly however.

"go get gopkg.in/jarcoal/httpmock.v1" works fine.

The same problem occurs for the older github/jarcoal/httpmock version. We have seen this problem on multiple machines.

On my particular machine, GOROOT, GOPATH (single directory) and GOBIN (= GOPATH + "\bin") environment variables are all set.

Are there any other variables or other specific Go setup that needs to be done in order for "go get" to properly install the httpmock package or is there a bug in the httpmock repository system somewhere?

Thank you!

http.DefaultTransport is hardcoded

http.DefaultTransport is hardcoded, this prevents httpmock from being used with some libraries like appengine/urlfetch which doesn't use http.DefaultTransport.

incompatible with goquery

httpmock.Activate()
defer httpmock.DeactivateAndReset()

httpmock.RegisterResponder("GET", "https://api.mybiz.com/articles.html",
  httpmock.NewStringResponder(200, `<html>...</html>`))


// and

goquery.NewDocument("https://api.mybiz.com/articles.html")

Will give Response.Request is nil

Since goquery looks at the Response property which seems to not be populated

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.