Code Monkey home page Code Monkey logo

gock's Introduction

gock GitHub release GoDoc Coverage Status Go Report Card license

Versatile HTTP mocking made easy in Go that works with any net/http based stdlib implementation.

Heavily inspired by nock. There is also its Python port, pook.

To get started, take a look to the examples.

Features

  • Simple, expressive, fluent API.
  • Semantic API DSL for declarative HTTP mock declarations.
  • Built-in helpers for easy JSON/XML mocking.
  • Supports persistent and volatile TTL-limited mocks.
  • Full regular expressions capable HTTP request mock matching.
  • Designed for both testing and runtime scenarios.
  • Match request by method, URL params, headers and bodies.
  • Extensible and pluggable HTTP matching rules.
  • Ability to switch between mock and real networking modes.
  • Ability to filter/map HTTP requests for accurate mock matching.
  • Supports map and filters to handle mocks easily.
  • Wide compatible HTTP interceptor using http.RoundTripper interface.
  • Works with any net/http compatible client, such as gentleman.
  • Network timeout/cancelation delay simulation.
  • Extensible and hackable API.
  • Dependency free.

Installation

go get -u github.com/h2non/gock

API

See godoc reference for detailed API documentation.

How it mocks

  1. Intercepts any HTTP outgoing request via http.DefaultTransport or custom http.Transport used by any http.Client.
  2. Matches outgoing HTTP requests against a pool of defined HTTP mock expectations in FIFO declaration order.
  3. If at least one mock matches, it will be used in order to compose the mock HTTP response.
  4. If no mock can be matched, it will resolve the request with an error, unless real networking mode is enable, in which case a real HTTP request will be performed.

Tips

Testing

Declare your mocks before you start declaring the concrete test logic:

func TestFoo(t *testing.T) {
  defer gock.Off() // Flush pending mocks after test execution

  gock.New("http://server.com").
    Get("/bar").
    Reply(200).
    JSON(map[string]string{"foo": "bar"})

  // Your test code starts here...
}

Race conditions

If you're running concurrent code, be aware that your mocks are declared first to avoid unexpected race conditions while configuring gock or intercepting custom HTTP clients.

gock is not fully thread-safe, but sensible parts are. Any help making gock more reliable in this sense is appreciated.

Define complex mocks first

If you're mocking a bunch of mocks in the same test suite, it's recommended to define the more concrete mocks first, and then the generic ones.

This approach usually avoids matching unexpected generic mocks (e.g: specific header, body payload...) instead of the generic ones that performs less complex matches.

Disable gock traffic interception once done

In other to minimize potential side effects within your test code, it's a good practice disabling gock once you are done with your HTTP testing logic.

A Go idiomatic approach for doing this can be using it in a defer statement, such as:

func TestGock (t *testing.T) {
	defer gock.Off()

	// ... my test code goes here
}

Intercept an http.Client just once

You don't need to intercept multiple times the same http.Client instance.

Just call gock.InterceptClient(client) once, typically at the beginning of your test scenarios.

Restore an http.Client after interception

NOTE: this is not required is you are using http.DefaultClient or http.DefaultTransport.

As a good testing pattern, you should call gock.RestoreClient(client) after running your test scenario, typically as after clean up hook.

You can also use a defer statement for doing it, as you do with gock.Off(), such as:

func TestGock (t *testing.T) {
	defer gock.Off()
	defer gock.RestoreClient(client)

	// ... my test code goes here
}

Examples

See examples directory for more featured use cases.

Simple mocking via tests

package test

import (
  "io/ioutil"
  "net/http"
  "testing"

  "github.com/nbio/st"
  "github.com/h2non/gock"
)

func TestSimple(t *testing.T) {
  defer gock.Off()

  gock.New("http://foo.com").
    Get("/bar").
    Reply(200).
    JSON(map[string]string{"foo": "bar"})

  res, err := http.Get("http://foo.com/bar")
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)

  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body)[:13], `{"foo":"bar"}`)

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

Request headers matching

package test

import (
  "io/ioutil"
  "net/http"
  "testing"

  "github.com/nbio/st"
  "github.com/h2non/gock"
)

func TestMatchHeaders(t *testing.T) {
  defer gock.Off()

  gock.New("http://foo.com").
    MatchHeader("Authorization", "^foo bar$").
    MatchHeader("API", "1.[0-9]+").
    HeaderPresent("Accept").
    Reply(200).
    BodyString("foo foo")

  req, err := http.NewRequest("GET", "http://foo.com", nil)
  req.Header.Set("Authorization", "foo bar")
  req.Header.Set("API", "1.0")
  req.Header.Set("Accept", "text/plain")

  res, err := (&http.Client{}).Do(req)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)
  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body), "foo foo")

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

Request param matching

package test

import (
  "io/ioutil"
  "net/http"
  "testing"

  "github.com/nbio/st"
  "github.com/h2non/gock"
)

func TestMatchParams(t *testing.T) {
  defer gock.Off()

  gock.New("http://foo.com").
    MatchParam("page", "1").
    MatchParam("per_page", "10").
    Reply(200).
    BodyString("foo foo")

  req, err := http.NewRequest("GET", "http://foo.com?page=1&per_page=10", nil)

  res, err := (&http.Client{}).Do(req)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)
  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body), "foo foo")

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

JSON body matching and response

package test

import (
  "bytes"
  "io/ioutil"
  "net/http"
  "testing"
	
	"github.com/nbio/st"
  "github.com/h2non/gock"
)

func TestMockSimple(t *testing.T) {
  defer gock.Off()

  gock.New("http://foo.com").
    Post("/bar").
    MatchType("json").
    JSON(map[string]string{"foo": "bar"}).
    Reply(201).
    JSON(map[string]string{"bar": "foo"})

  body := bytes.NewBuffer([]byte(`{"foo":"bar"}`))
  res, err := http.Post("http://foo.com/bar", "application/json", body)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 201)

  resBody, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(resBody)[:13], `{"bar":"foo"}`)

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

Mocking a custom http.Client and http.RoundTripper

package test

import (
  "io/ioutil"
  "net/http"
  "testing"

  "github.com/nbio/st"
  "github.com/h2non/gock"
)

func TestClient(t *testing.T) {
  defer gock.Off()

  gock.New("http://foo.com").
    Reply(200).
    BodyString("foo foo")

  req, err := http.NewRequest("GET", "http://foo.com", nil)
  client := &http.Client{Transport: &http.Transport{}}
  gock.InterceptClient(client)

  res, err := client.Do(req)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)
  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body), "foo foo")

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

Enable real networking

package main

import (
  "fmt"
  "io/ioutil"
  "net/http"

  "github.com/h2non/gock"
)

func main() {
  defer gock.Off()
  defer gock.DisableNetworking()

  gock.EnableNetworking()
  gock.New("http://httpbin.org").
    Get("/get").
    Reply(201).
    SetHeader("Server", "gock")

  res, err := http.Get("http://httpbin.org/get")
  if err != nil {
    fmt.Errorf("Error: %s", err)
  }

  // The response status comes from the mock
  fmt.Printf("Status: %d\n", res.StatusCode)
  // The server header comes from mock as well
  fmt.Printf("Server header: %s\n", res.Header.Get("Server"))
  // Response body is the original
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Printf("Body: %s", string(body))
}

Debug intercepted http requests

package main

import (
	"bytes"
	"net/http"
	
  "github.com/h2non/gock"
)

func main() {
	defer gock.Off()
	gock.Observe(gock.DumpRequest)

	gock.New("http://foo.com").
		Post("/bar").
		MatchType("json").
		JSON(map[string]string{"foo": "bar"}).
		Reply(200)

	body := bytes.NewBuffer([]byte(`{"foo":"bar"}`))
	http.Post("http://foo.com/bar", "application/json", body)
}

Hacking it!

You can easily hack gock defining custom matcher functions with own matching rules.

See add matcher functions and custom matching layer examples for further details.

License

MIT - Tomas Aparicio

gock's People

Contributors

123hurray avatar appleboy avatar bogdanpetrea avatar cakejelly avatar cuishuang avatar danny-cheung avatar dtluna avatar elliotwms avatar fuwensun avatar gabrielf avatar grahamwalters avatar h2non avatar halfi avatar iktas avatar iliacimpoes avatar marchelbling avatar maxcnunes avatar moeryomenko avatar pbartlett-oi avatar samihda avatar steinfletcher avatar treythomas123 avatar v3n avatar wfscot avatar wilianto 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gock's Issues

Thank You

Hey @h2non
Just wanted to say thank you on behalf of my team and I (we're currently hosted on Bitbucket) for creating such an invaluable tool that we use daily in our product.

Love, Anak Kandang Team.
From Jakarta, Indonesia.

Multiple mocks matchers

So I was writing some tests for my code.
In one of my functions I was calling two APIs (for different purposes). So I needed to have two mockers. one of them(route2) should have had a matcher for the request body while the other (route1) did not. (For this, I had make two mockers with gock.New)
Then I traced an unexpected behavior. When I was calling the API to route2, the matcher registered on route1 mocker was being called.
Therefore, I looked up in the code to see the reason and I found out that there was a global variable named "Matchers" in "matcher.go". And this causes all the mockers to have the same matchers which I believe is a bug.
My test code:

	//route1
	gock.New("http://emad.host").
		Get("/notifications/bucketname").
		Reply(200).
		JSON(map[string]interface{}{
		"ok": "ok",
	})
	//route2
	gock.New("http://emad.host").
		Put("/notifications/bucketname").
		AddMatcher(func(r *http.Request, request *gock.Request) (bool, error) {
		fmt.Println("matcher called")
		return true, nil
	}).Reply(400)

	client := &http.Client{}

	//this request would call matcher of route2 (unexpected behaviour)
	request1, _ := http.NewRequest("GET", "http://emad.host/notifications/bucketname", nil)
	fmt.Println(client.Do(request1))

	request2, _ := http.NewRequest("PUT", "http://emad.host/notifications/bucketname", bytes.NewReader([]byte(`hello world`)))
	fmt.Println(client.Do(request2))

Error using gock v.1.0.13 with go modules

Overview

gock v1.0.13 appears to depend on the parth repository. Using normal go get -u gopkg.in/h2non/gock.v1 in a go modules environment results in the following error:

../../go/pkg/mod/gopkg.in/h2non/[email protected]/matchers.go:123:13: undefined: parth.Sequent

This appears to be caused by the go modules version resolver which somehow imports perth v.1.1.3 as a transitive dependency, instead of the v.2.0.0.

Currently this can be fixed by pinning gock to version v.1.0.12 in the go.mod file of the project using gock.

System Information

OS version: Ubuntu 18.04
Go version: 1.11.1 linux/amd64

How to simulate

  1. Create a go project outside the $GOPATH, using go mod init
  2. Run go get -u gopkg.in/h2non/gock.v1 to add gock as a module dependency.

HTTP Request with roundtripper is not being intercepted

Hi,

In my code I do a POST request to a service but before the request is executed I add a http.RoundTripper to add a header to my request. When I comment this code out gock intercepts the request but with the RoundTripper added gock does not seem to intercept the request. Any idea on how to fix it?

Thanks in advance!

When in networking mode and mock matches still NativeTransport.RoundTrip response used if error occurs

Hi,

I test my application A using it's HTTP API. During the test my application calls application B using HTTP API. I would like to mock application B response using gock. I've learned that I have to use networking mode, otherwise my calls to A would fail.

However, even though I created a mock that matches the request issued by application A towards application B, it is not used because of code lines below with my comments added (link to the code in github):

if networking { // true
	res, err = m.Transport.RoundTrip(req) // res == nil, err != nil
	// In no mock matched, continue with the response
	if err != nil || mock == nil { // as err from native transport is not nil, because app B host cannot be reached, native transport res is returned
		return res, err // line reached and nil res returned with non-nil err
	}
}

return Responder(req, mock.Response(), res)

From the gock's readme I understood that mock takes precedence over NativeTransport in networking mode. The comment from this line additionally enforces me in such understanding. What's your view?

Daniel

Body matching for Request

I'm trying to match the body of a request as shown below using BodyString on Request. However I am receiving gock: cannot match any request. When I use it without BodyString it is fine. gock.Observe(gock.DumpRequest) confirms the value is indeed in the request. Any help much appreciated.

func TestContentClient_UpdateNode(t *testing.T) {
	dummy := struct {
		ServerUrl string
		Token     string
		NodeId    string
		Body      string
	}{
		ServerUrl: "http://test.server",
		Token:     "TOKEN",
		NodeId:    "100",
		Body:      "Hello",
	}

	defer gock.Off()
	gock.Observe(gock.DumpRequest)
	gock.New(dummy.ServerUrl).
		Put("/nodes/"+dummy.NodeId+"/content").
		MatchHeader("Content-Type", "application/octet-stream").
		BodyString(dummy.Body).
		Reply(http.StatusOK).
		JSON(NodeEntry{
			Node{
				ID: dummy.NodeId,
			},
		})

	client := NewContentClient(dummy.ServerUrl, dummy.Token)
	node, err := client.UpdateNode(dummy.NodeId, dummy.Body)

	assert.NoError(t, err)
	assert.Equal(t, dummy.NodeId, node.ID)
}

client timeout not working

context.WithTimeout()
http.DefaultClient.Do(taskReq.WithContext(cxt))

not working when mocking with gock.

Any idea to test the timeout?

MatchHeader does match if value has special characters (., /, ;, etc)

gock.MatchHeader accepts two strings (key, value), but the underlying function that matches the mock request Headers against the real request headers is regexp.MatchString. (File: matchers.go)

The issue is that regexp.MatchString takes a regex pattern expression and a string.

That causes the problem of matching headers that have parentheses or other special characters.

Example:

// main.go

req, err := http.NewRequest("GET", "http://example.com", nil)
req.Header.Add("User-Agent", "Agent (version1.0)")

// main_test.go

gock.New("http://example.com").
  MatchHeader("User-Agent", "Agent (version1.0)").  // Will never match the request
  Get("/").
  Reply(200).
  BodyString("Success")

A way of fixing the issue is that the key and value are escaped first using regexp.QuoteMeta(key) & regexp.QuoteMeta(value), before being passed to the regexp.MatchString function.

matchers.go

for _, field := range req.Header[key] {
        escapedValue := regexp.QuoteMeta(value[0])  // Something like this
        escapedField := regexp.QuoteMeta(field)
	match, err = regexp.MatchString(escapedValue, escapedField)
	if err != nil {
		return false, err
	}
	if match {
		break
	}
}

Testing http.Client.Timeout value with retries

Hello,

Great lib!

I'm trying to test retries with a specific http.Client.Timeout value. Response.Delay does not seem to work as expected. I set it to 60 and I set my http.Client.Timeout to 5. My retries are also set to retry after Client.Timeout. When I do this and run the following test it does not seem to timeout as expected. What I expect to happen is to retry twice after a maximum of 5 seconds per request. What happens instead is the test takes much longer to run. Any idea of a workaround or area of the gock code that might change to make this work? Happy to submit a PR for this with your guidance. Thanks.

         gock.New(url).
		Post("/endpoint").
		Response.
		Delay(60 * time.Second)

          gock.New(url).
		Post("/endpoint").
		Response.
		Delay(60 * time.Second)


	gock.New(url).
		Post("/endpoint").
		MatchHeaders(expectedRequestHeaders).
		Reply(http.StatusCreated)

	client := CreateHTTClientAdapter()
	gock.InterceptClient(client.GetHTTPClient())
        resp,err := client.Post(generateBody(), test.CreateStandardHeaders())

	assert.Nil(suite.T(), err, "err should be nil and should handle error through response")
	assert.Equal(suite.T(), http.StatusCreated, resp.Status, "status should be 201/Created")

Content-Type in Request.XML()

Request.XML() implemented in a way it matches Content-Type of "application/xml". I encountered a third-party API where I need to send "text/xml". I tried to use MatchType later in a chain, but it seems counter-intuitive (and didn't match in my case, but may be it's due another cause).

I think, it's, probably, more clear to have separate calls to API, like: gock.Post(...).MatchType(...).XML(...). Another option is to add optional parameter to XML() (or add a new method with parameter).

Can't intercept 3rd party initiated request

Hi, I was wondering how does gock intercepts an outgoing HTTP.

We use API client generated by swagger-codegen to access our other services, so any HTTP traffic are handled inside the said library, not in our packages. And it seems that gock were unable to intercepts any outgoing HTTP request originating from this API client. There's no issue if the HTTP request coming from the code residing in the same package as when gock is invoked.

gock.New(baseUrl).Get(path).Reply(404)

// this will produces the expected result
resp, _ := http.Get(url)

// this will not, the handler type is from another package (the API Client)
result, _ := handler.GetData(param1, param2, param3)

Non-matching path not detected

The following test passes: even though "/b" is the expected path and "/bar" is the actual path:

func TestA(t *testing.T) {                                                      
    // Passes -- but shouldn't                                                  
    defer gock.Off()                                                            
                                                                                
    gock.New("http://foo").                                                     
        Get("/b").                                                              
        Reply(http.StatusOK).                                                   
        BodyString("Some text")                                                 
                                                                                
    c := &http.Client{}                                                         
    c.Get("http://foo/bar")                                                     
    assert.Equal(t, true, gock.IsDone())                                        
}

Is this expected behaviour?

Using a regex ($) seems to give the behaviour I'd expect (for matching and non-matching cases):

func TestB(t *testing.T) {                                                      
    // Fails -- correctly                                                       
    defer gock.Off()                                                            
                                                                                
    gock.New("http://foo").                                                     
        Get("/b($)").                                                           
        Reply(http.StatusOK).                                                   
        BodyString("Some text")                                                 
                                                                                
    c := &http.Client{}                                                         
    c.Get("http://foo/bar")                                                     
    assert.Equal(t, true, gock.IsDone())                                        
}

Thanks.

AddMatch

AddMatch only use once in a go program?

package main

import (
"fmt"
"net/http"
"regexp"
"gopkg.in/h2non/gock.v1"
)

func test_a() {
defer gock.Off()

gock.New("http://httpbin.org").Get("/").
	AddMatcher(func(req *http.Request, ereq *gock.Request) (bool, error) {
	matched, err := regexp.MatchString("/aa/[A-Za-z0-9]{6}/ii/[A-Za-z0-9]{6}/calculator", req.URL.Path)
	return matched && "GET" == req.Method, err
}).
	Reply(204).
	SetHeader("Server", "gock")

res, err := http.Get("http://httpbin.org/aa/123456/ii/123456/calculator")
if err != nil {
	fmt.Errorf("Error: %s", err)
}

fmt.Printf("Status: %d\n", res.StatusCode)
fmt.Printf("Server header: %s\n", res.Header.Get("Server"))

}

func test_b() {
defer gock.Off()
gock.New("http://httpbin.org").
Get("/application").
Reply(200).
SetHeader("Server", "gockbin")

res, err := http.Get("http://httpbin.org/application")
if err != nil {
	fmt.Errorf("Error: %s", err)
}
fmt.Printf("Status: %d\n", res.StatusCode)
fmt.Printf("Server header: %s\n", res.Header.Get("Server"))

}

func main() {
test_a()
test_b()
}

Panic after setting BodyBuffer for GET request

I'm new to gock and I'm fiddling with it to get some hands-on experience. This is when I got a panic and 1st it wasn't trivial what's going on. As I understand it now: I got a panic because I set an HTTP body matcher on a GET request. Could we maybe improve the user experience, maybe just by panicking sooner, i.e., when setting the body matcher?

Here is how to reproduce the panic:

package main

import (
	"log"
	"net/http"

	"github.com/h2non/gock"
)

func main() {
	const url = "http://example.com"
	gock.New(url).BodyString("foo")
	if _, err := http.Get(url); err != nil {
		log.Fatal(err)
	}
}

The panic itself:

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=0x18 pc=0x4d39dd]

goroutine 1 [running]:
io/ioutil.readAll.func1(0xc0001158a8)
        /usr/lib/go/src/io/ioutil/ioutil.go:30 +0x106
panic(0x6c1b20, 0x8edce0)
        /usr/lib/go/src/runtime/panic.go:969 +0x175
bytes.(*Buffer).ReadFrom(0xc000115830, 0x0, 0x0, 0x70f3c0, 0x10, 0x0)
        /usr/lib/go/src/bytes/buffer.go:204 +0x7d
io/ioutil.readAll(0x0, 0x0, 0x200, 0x0, 0x0, 0x0, 0x0, 0x0)
        /usr/lib/go/src/io/ioutil/ioutil.go:36 +0xe5
io/ioutil.ReadAll(...)
        /usr/lib/go/src/io/ioutil/ioutil.go:45
github.com/h2non/gock.MatchBody(0xc00010e000, 0xc00009d5f0, 0x7f52ef684001, 0x0, 0x0)
        /home/frncmx/code/src/github.com/h2non/gock/matchers.go:174 +0x10e
github.com/h2non/gock.(*MockMatcher).Match(0xc0000a82e0, 0xc00010e000, 0xc00009d5f0, 0x108, 0x0, 0xc00004e9e0)
        /home/frncmx/code/src/github.com/h2non/gock/matcher.go:113 +0x77
github.com/h2non/gock.(*Mocker).Match(0xc00009ade0, 0xc00010e000, 0x1, 0x255e2, 0xc00004ea40)
        /home/frncmx/code/src/github.com/h2non/gock/mock.go:113 +0x145
github.com/h2non/gock.MatchMock(0xc00010e000, 0xc00004eaf8, 0x40efb0, 0xc00009ae40, 0x30)
        /home/frncmx/code/src/github.com/h2non/gock/matcher.go:128 +0x7b
github.com/h2non/gock.(*Transport).RoundTrip(0xc0000a8280, 0xc00010e000, 0x0, 0x0, 0x0)
        /home/frncmx/code/src/github.com/h2non/gock/transport.go:59 +0x95
net/http.send(0xc00010e000, 0x767a80, 0xc0000a8280, 0x0, 0x0, 0x0, 0xc0000b6040, 0x203000, 0x1, 0x0)
        /usr/lib/go/src/net/http/client.go:252 +0x453
net/http.(*Client).send(0x8f9940, 0xc00010e000, 0x0, 0x0, 0x0, 0xc0000b6040, 0x0, 0x1, 0xc00010e000)
        /usr/lib/go/src/net/http/client.go:176 +0xff
net/http.(*Client).do(0x8f9940, 0xc00010e000, 0x0, 0x0, 0x0)
        /usr/lib/go/src/net/http/client.go:718 +0x45f
net/http.(*Client).Do(...)
        /usr/lib/go/src/net/http/client.go:586
net/http.(*Client).Get(0x8f9940, 0x710115, 0x12, 0xc0000b2288, 0x3, 0x8)
        /usr/lib/go/src/net/http/client.go:475 +0xbe
net/http.Get(...)
        /usr/lib/go/src/net/http/client.go:447
main.main()
        /home/frncmx/.config/JetBrains/GoLand2020.2/scratches/scratch_7.go:13 +0xbd

I think the root cause might be the same with #70

Ability to flush only certain mocks

Right now you can only flush all of the mocks, right? What if I want to flush only certain mocks because I want some mocks to remain?

The case: I've started my service before running any tests, my service fetching some URLs during tests (just by timer), so I want some mocks to remain during all tests run, but at the same time I want to flush test-mocks after each test run.

Allow connections to an httptest Server

Hi,

I'm finding gock extremely useful, however I have a test where I need to make a real call to an httptest Server which will then spawn a couple of requests which gock should intercept.
However, I can't seem to find a way to do it. I tried enabling networking and filtering, which makes it work, but it won't call the actual server, it just mocks that call, too.

It("receives a complete trigger [DOC]", func() {
  defer gock.DisableNetworking()
  defer gock.DisableNetworkingFilters()
  gock.EnableNetworking()
  var a args
  a.Host = docServer.URL
  a.Path = "/triggers"
  a.Body = completeTrigger
  a.Method = "POST"
  a.Headers = map[string]string{
    "Authorization": "Token token=" + configuration.Config.AppToken,
    "Content-Type":  middleware.MimeType,
    "Accept":        middleware.MimeType,
  }
  gock.NetworkingFilter(func(req *http.Request) bool {
    return req.URL.String() == docServer.URL
  })
  gock.New(docServer.URL).
    Post("/triggers").
    Reply(201)

  // here are the actual mocks I need

  resp, err := a.run()
  Expect(err).ToNot(HaveOccurred())
  Expect(resp.StatusCode).To(Equal(201))
  Expect(gock.IsDone())
})

The first Expect will generate this error:

Expected error:
    <*url.Error | 0xc4204040f0>: {
        Op: "Post",
        URL: "http://127.0.0.1:59186/triggers",
        Err: {
            s: "gock: cannot match any request",
        },
    }
    Post http://127.0.0.1:59186/triggers: gock: cannot match any request
not to have occurred

Am I missing something?

Thanks a lot for your help!

Gock: cannot match any request json

Hey

Here's my code:

    defer gock.Off()
    gock.New("https://foo.com").
    Post("/bar").
    MatchHeader("Authorization", "12345").
     MatchHeader("Accept", "^"+regexp.QuoteMeta("application/vnd.api+json")+"$").
     MatchHeader("Content-Type", "^"+regexp.QuoteMeta("application/vnd.api+json")+"$").
   // MatchType("json").
   // JSON(map[string]string{"foo": "bar"}).
     Reply(201).
     JSON(map[string]string{"bar": "foo"})

      var reqBody io.Reader
      body:=`{"foo": "bar"}`
      fmt.Println(body)
      bodied := json.RawMessage(body)
      jsonDocument, err1 = json.Marshal(bodied)
      reqBody = bytes.NewReader(jsonDocument)
      statusCode, resBody, err = request("https://foo.com/bar", "POST", "12345", reqBody)

And the request function:

func request(url string, method string, authorization string, body io.Reader) (int, interface{}, error)
{
	req, _ := http.NewRequest(method, url, body)
	req.Header.Add("Content-Type", applicationType)
	req.Header.Add("Authorization","Bearer "+authorization)
	req.Header.Add("Accept", applicationType)
	client := &http.Client{}
	res, err := client.Do(req)
....
}

Works fine without the MatchType("json") and JSON(json.RawMessage({"foo": "bar"})). When I comment either of them, the request fails and prints

gock: cannot match any request

I've tried changing many things. Including: removing the RawMessage transformation, changing the body definition e,g. body:=map[string]string{"foo": "bar"}.

Not sure what I am doing wrong, can you recommend something?

Edit: Using the request function in an actual deployment does work with {"foo": "bar"}, but not in Gock.

ioutil.ReadAll error testing.

I am trying to test the following line of code:

func ook() error {
        […]
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return errors.Wrap(err, "cannot read body, trying again")
	}

This is my test:


func (errReader) Read(p []byte) (int, error) {
	return 1, errors.New("Computer says NON!")
}

// Wait for vault to unseal: body error.
func TestWaitForVaultToUnsealBodyError(t *testing.T) {
	defer gock.Off() // Flush pending mocks after test execution

	gock.New(URL).
		Get("v1/seal-status").
		Reply(200).
		Body(errReader{})

        ook()
}

I removed the URL and other extra stuff, the code is a little (but not much) more complex than that. However, the ioutil.ReadAll refuses to spew an error. What am I doing wrong?

Only mock a certain URL

Hi,
It's not obvious to me how I can mock only the URLs I want and let the other requests pass.

requestMock := gock.New("test.com")
// Return empty list of tokens
requestMock.Get("/api/v1/users").
	Persist().
	Reply(200).
	JSON(map[string][]string{})

When running the tests I get:

Expected error:
          <*url.Error | 0xc000a2d440>: {
              Op: "Get",
              URL: "http://127.0.0.1:34161/api?timeout=32s",
              Err: {
                  s: "gock: cannot match any request",
              },
          }
          Get http://127.0.0.1:34161/api?timeout=32s: gock: cannot match any request
      not to have occurred

I don't want to mock http://127.0.0.1:34161/api?timeout=32s.

I have tried .EnableNetworking(), but I don't get the mocked response. I get something like this instead:

{"error": "Get test.com/api/v1/users: unsupported protocol scheme \"\""}

Simulate a http client get timeout

Is there a way to simulate a http client timeout?

I am struggling to find a way how to implement that.

It would be nice to have an example of that on the docs.

I am planning to open a PR with that, if I find a solution in the the meanwhile.

Thanks

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

access request body from ReplyFunc ?

Is it possible to access the request body in the ReplyFunc ?

gock.New(myEndpoint).
	Post("/scim/v2/Groups").
	Persist().
	ReplyFunc(func(response *gock.Response) {
		response.???
	})

Improve MatchBody() by ignoring order of JSON key/values

Hello,

I had an issue regarding trying to match JSON payloads with a mocked response even though the keys/values matched exactly. In my search for figuring out why it wasn't working, I noticed that the section in which a check for equality is sensitive to the order by which keys and values are present in the casted string.

My approach to solving this is (at least for JSON) is to convert the byte bodies into a map[string]interface{} and check equality using reflect.DeepEqual(x,y).

I will open a PR shortly with my suggested fixes. I'd like to merge this into master if possible, please let me know if you have any suggestions on how to implement this better.

PR: #16

Thank you 👍

gock: cannot match any request

I keep getting this error no matter what I do with this mock.
This is the mock:

gock.New("http://www.espn.com").
        Get("/nfl/player/gamelog/_/id/16733/year/2015/").
        Reply(200).
        File("testdata/espn_gamelog_2015.html")

And this is the error I get:
Failed to query ESPN: Get http://espn.go.com/nfl/player/gamelog/_/id/16733/year/2015/: gock: cannot match any request"

As you can see it's the exact same URL. What's wrong?

gock: cannot match any request In more one http request

I have a code. It can work before 1.0.14. but in 1.0.14. It can't work

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"gopkg.in/h2non/gock.v1"
)

func main() {
	data := `{"code":0,"msg":"ok"}`
	gock.New("http://big.tree.com").
		MatchParams(map[string]string{
			"moduleName": "MySQL",
		}).
		Reply(200).
		BodyString(data)
	defer gock.Off()
	resp, err := http.Get("http://big.tree.com?moduleName=MySQL")
	defer resp.Body.Close()
	if err != nil {
		panic(err)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(body))
	resp2, err := http.Get("http://big.tree.com?moduleName=MySQL")
	if err != nil {
		panic(err)
	}
	body, err = ioutil.ReadAll(resp2.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(body))
}

the result is

{"code":0,"msg":"ok"}
panic: Get http://big.tree.com?moduleName=MySQL: gock: cannot match any request

goroutine 1 [running]:
main.main()
        F:/newbr/t1/main.go:32 +0x502

gopkg url leads to wrong (older?) version

I installed gock using the specified gopkg.in url:
go get -u gopkg.in/h2non/gock.v0
And I'm pretty sure it installed a really old version, because .Get() did not exist. Are we supposed to specify the version ourselves? If so, maybe add a hint about that (for the people like me that have not come across a gopkg url before)?

Allow specify url.Values as query paramenter

Hi,
thanks for this amazing project!

I've a function like this

func MakeRequest() {
  query := url.Values{}
  query.Add("key1", "value1")
  query.Add("key2", "value2")
  queryString := query.Encode()
  requestURL := fmt.SPrintf("%s?%s, "http://foo.com/bar", queryString)
  res, err := http.Get(requestURL)
  ....
}

I would like to test it. The simplest way to to that is

func Test(t *testing.T) {
  gock.New("http://foo.com").
    Get("/bar").
    MatchParam("key1", "value1").
    MatchParam("key2", "value2").
    Reply(200).
    JSON(map[string]string{"foo": "bar"})
}

Anyway:

  1. this can be a little verbose when the query parameters are a lot
  2. the check is not made against an exactly value

I would like to write something like that:

func Test(t *testing.T) {
  query, err := url.ParseQuery("key1=value1&key2=value2")
  gock.New("http://foo.com").
    Get("/bar").
    MatchExactParamValue(query).
    Reply(200).
    JSON(map[string]string{"foo": "bar"})
}

The check is made exactly using url.Values struct.

Another proposal can be

func Test(t *testing.T) {
  gock.New("http://foo.com").
    Get("/bar").
    MatchParam("key1", "value1").
    MatchParam("key2", "value2").
    MatchParamExactly().
    Reply(200).
    JSON(map[string]string{"foo": "bar"})
}

If you are interested in, I'll send a PR for that implementation or a similar one

Compression type matching and automatic decompression

It'd be nice to have a way to specify a compression type, for testing clients that gzip their body contents. For example:

gock.New(url).
    Post("/path").
    MatchCompression("gzip").
    JSON(map[string]interface{}{
        "foo": "bar",
    }).
    Reply(200)

To accomplish this now requires a custom matcher, since the JSON matcher assumes the request body is unencoded.

I can write a PR if you're interested in including this.

Thanks!

Assert a Mock response only occurs once

I'd like to assert that a mocked call occurs once. What is the best way to do this with the Gock library?

For example, with the following mock:

    defer gock.Off()
    gock.New("http://example.com").
          Get("/oauth2/abcd/v1/keys").
          Reply(http.StatusOK).
          JSON("{\"foo\":\"bar\")

I want to make sure that endpoint is only called once.

*Request.HeaderPresent not working in v1.0.16

I have Test Code like this,

func TestHitHTTP(t *testing.T) {
	// create custom HTTP client
	httpClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	// define URL
	URL := "https://ayssiz.com"

	// define mock
	gock.InterceptClient(httpClient)
	defer gock.Off()
	defer gock.RestoreClient(httpClient)

	// create mock response
	mockResponse := make(map[string]interface{})
	mockResponse["success"] = true

	gock.New(URL).
		HeaderPresent("KEY").
		Reply(200).
		JSON(mockResponse)

	// hit HTTP
	hitHttp(httpClient, URL)

	assert.Equal(t, true, gock.IsDone())
}


func hitHttp(httpClient *http.Client, URL string) (interface{}, error) {
	var jsonBody interface{}

	request, err := http.NewRequest("POST", URL, nil)
	request.Header.Set("KEY", "APIKEY")

	response, err := httpClient.Do(request)
	if err != nil {
		return jsonBody, err
	}

	defer response.Body.Close()
	json.NewDecoder(response.Body).Decode(&jsonBody)

	return jsonBody, nil
}

I use HeaderPresent to check wheter the header key is present or not. Previously it works fine in v1.0.15,
but when I upgrade it to v1.0.16, it is not working. The value of gock.IsDone() is false, which mean the mock is not hit by the httpClient

--- FAIL: TestHitHTTP (0.00s)
module_test.go:43:
Error Trace: module_test.go:43
Error: Not equal:
expected: true
actual : false
Test: TestHitHTTP
FAIL

Not match any requests

I'm doing tests with Consul lib, and I'm trying to intercept the requests to Consul but I'm receiving the following error:

Expected nil, but got: &url.Error{Op:"Get", URL:"http://127.0.0.1:8500/v1/kv/bots/my-bot/?recurse=", Err:(*net.OpError)(0xc0000ba3c0)}

that means that I'm not intercepting the requests to Consul, and this is my code:

func TestGetBotById(t *testing.T) {
	consulURL := fmt.Sprintf("/v1/kv/bots/%s/", fakeBotID)
	consulData := helperLoadBytes(t, "consul/bots.json")

	defer gock.Off()

	gock.New("http://127.0.0.1:8500").
		Get(consulURL).
		MatchParams(map[string]string{
			"recurse": "",
		}).
		Persist().
		Reply(http.StatusOK).
		BodyString(string(consulData))

	botInfo, err := helpers.GetBotByID(fakeBotID)
	expectedValue := map[string]string{
		"host": "my-host",
		"port": "3000",
	}
	assert.Nil(t, err)
	assert.NotNil(t, botInfo)
	assert.Equal(t, expectedValue, botInfo, "should be equals to")
	assert.True(t, gock.IsDone(), true)
}

the function helpers.GetBotById is making the requests to Consul but grock can't intercept it

does someone has seen the same error?

Multiple mocks for the same path

package main

import (
	"fmt"
	"gopkg.in/h2non/gock.v1"
	"net/http"
)

func main() {
	defer gock.Off()

	gock.New("https://blah.com").Path("/path").
		AddMatcher(func(request *http.Request, request2 *gock.Request) (b bool, e error) {
			fmt.Println("Matcher001")
			return false, nil
		}).
		Reply(200)

	gock.New("https://blah.com").Path("/path").
		AddMatcher(func(request *http.Request, request2 *gock.Request) (b bool, e error) {
			fmt.Println("Matcher002")
			return false, nil
		}).
		Reply(200)

	gock.New("https://blah.com").Path("/path").
		AddMatcher(func(request *http.Request, request2 *gock.Request) (b bool, e error) {
			fmt.Println("FinalMatcher")
			return true, nil
		}).
		Reply(200)

	http.Get("https://blah.com/path")
}

Expected Output:

Matcher001
Matcher002
FinalMatcher

Actual Output:

Matcher001
Matcher001
Matcher001

SetError not implemented properly

When using this gock:
gock.New("http://www.google.com"). Get("/").Reply(500).SetError(errors.New("Internal Server Error"))

The following line is printed:
2016/04/18 12:14:03 RoundTripper returned a response & error; ignoring response

I'm guessing the RoundTripper is supposed to return a nil response when the error is set? Or I am supposed to set it to nil somehow?

Add examples

  • JSON, XML
  • RegExp
  • URL / Query Params
  • Multiple mocks
  • Persistent / Volatile mocks
  • Enable / Disable Networking mode
  • Match complex requests
  • Add custom matchers
  • Map / Filters use case

Invalid module versioning from h2non/parth

This would more appropriately be an issue on h2non/parth repo, but unfortunately issues are not enabled there. It's also not really resolvable with a pull request, unfortunately. (It's also possible to resolve purely in gock, see the end of this issue)

Currently, go.mod has the dependency:

github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542

This commit corresponds to the h2non/[email protected] tag.

As a result, downstream go.sum files end up with an entry for v2.0.1+incompatible because the target commit/tag is still using a v0/v1 path (no /v2 suffix) but is tagged as v2.0.1.

This then breaks the sumdb verification:

github.com/h2non/[email protected]+incompatible: reading https://proxy.golang.org/github.com/h2non/parth/@v/v2.0.1+incompatible.zip: 410 Gone
        server response: not found: github.com/h2non/[email protected]+incompatible: invalid version: +incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required

Would it be possible to merge the changes from h2non/parth@master branch to h2non/parth@v2 branch while ensuring that the module path ends with /v2 in go.mod and tagging a new version from that? Afterwards, gock could be updated to use the appropriately semantically versioned module.

Alternatively, since the only (current?) difference between h2non/parth and the original codemodus/parth is the module path, and the upstream does use proper semantic versions, gock could be changed to use that directly. If this is preferable, let me know, and I will happily open a pull request to make the change here!

golangci-lint complains that no export data for "gopkg.in/h2non/gock.v1"

I copied the example from the README and tried to run golangci-lint on it. This is what I got:

√ ; lsd -l ook.go
.rw-rw-r-- yann yann 294 B Fri Sep 18 12:06:18 2020  ook.go
√ ; bat ook.go
       File: ook.go
   1   package main
   2
   3   import (
   4       "testing"
   5
   6       "gopkg.in/h2non/gock.v1"
   7   )
   8
   9   func TestFoo(t *testing.T) {
  10       defer gock.Off() // Flush pending mocks after test execution
  11
  12       gock.New("http://server.com").
  13           Get("/bar").
  14           Reply(200).
  15           JSON(map[string]string{"foo": "bar"})
  16
  17       // Your test code starts here...
  18   }
√ ; golangci-lint run ook.go
WARN [runner] Can't run linter goanalysis_metalinter: S1033: failed prerequisites: [(inspect@command-line-arguments, isgenerated@command-line-arguments): analysis skipped: errors in package: [/home/yann/tmp/ook.go:6:2: could not import gopkg.in/h2non/gock.v1 (ook.go:6:2: cannot find module providing package gopkg.in/h2non/gock.v1: working directory is not part of a module) /home/yann/tmp/ook.go:10:8: undeclared name: gock /home/yann/tmp/ook.go:12:2: undeclared name: gock /home/yann/tmp/ook.go:6:2: "gopkg.in/h2non/gock.v1" imported but not used]]
WARN [runner] Can't run linter unused: buildir: failed to load package : could not load export data: no export data for "gopkg.in/h2non/gock.v1"
ERRO Running error: buildir: failed to load package : could not load export data: no export data for "gopkg.in/h2non/gock.v1"
✗ 3 ;

Am I doing something wrong? If so, what? If not, is that a bug? …

Setting BodyString on a Request causes nil pointer dereference

Setting BodyString to anything causes the test to crash.

	gock.New(skynet.DefaultDownloadOptions.PortalURL).
		Get(urlpath).
		BodyString("form-data").
		Reply(200).
		BodyString("test\n")
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	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=0x18 pc=0x10d3070]

goroutine 7 [running]:
testing.tRunner.func1(0xc000104100)
	/usr/local/Cellar/go/1.13.6/libexec/src/testing/testing.go:874 +0x3a3
panic(0x1318620, 0x15f7420)
	/usr/local/Cellar/go/1.13.6/libexec/src/runtime/panic.go:679 +0x1b2
io/ioutil.readAll.func1(0xc00012b600)
	/usr/local/Cellar/go/1.13.6/libexec/src/io/ioutil/ioutil.go:30 +0x101
panic(0x1318620, 0x15f7420)
	/usr/local/Cellar/go/1.13.6/libexec/src/runtime/panic.go:679 +0x1b2
bytes.(*Buffer).ReadFrom(0xc00012b598, 0x0, 0x0, 0x1620940, 0xc00012b5c0, 0x12c76b8)
	/usr/local/Cellar/go/1.13.6/libexec/src/bytes/buffer.go:204 +0x80
io/ioutil.readAll(0x0, 0x0, 0x200, 0x0, 0x0, 0x0, 0x0, 0x0)
	/usr/local/Cellar/go/1.13.6/libexec/src/io/ioutil/ioutil.go:36 +0x100
io/ioutil.ReadAll(...)
	/usr/local/Cellar/go/1.13.6/libexec/src/io/ioutil/ioutil.go:45
gopkg.in/h2non/gock%2ev1.MatchBody(0xc00017c000, 0xc000148270, 0xc00012b601, 0x0, 0x0)
	/Users/marcin/go/pkg/mod/gopkg.in/h2non/[email protected]/matchers.go:169 +0x10c
gopkg.in/h2non/gock%2ev1.(*MockMatcher).Match(0xc00015a0c0, 0xc00017c000, 0xc000148270, 0x161fde0, 0x2, 0xa)
	/Users/marcin/go/pkg/mod/gopkg.in/h2non/[email protected]/matcher.go:111 +0x77
gopkg.in/h2non/gock%2ev1.(*Mocker).Match(0xc00014a240, 0xc00017c000, 0x1, 0x8, 0xc00012b758)
	/Users/marcin/go/pkg/mod/gopkg.in/h2non/[email protected]/mock.go:113 +0x143
gopkg.in/h2non/gock%2ev1.MatchMock(0xc00017c000, 0x30, 0x13616c0, 0xc00012b800, 0x4500000)
	/Users/marcin/go/pkg/mod/gopkg.in/h2non/[email protected]/matcher.go:126 +0x7b
gopkg.in/h2non/gock%2ev1.(*Transport).RoundTrip(0xc00000e3a0, 0xc00017c000, 0x0, 0x0, 0x0)
	/Users/marcin/go/pkg/mod/gopkg.in/h2non/[email protected]/transport.go:59 +0xae
net/http.send(0xc00017c000, 0x13ea1c0, 0xc00000e3a0, 0x0, 0x0, 0x0, 0xc00015c028, 0x203000, 0x1, 0x0)
	/usr/local/Cellar/go/1.13.6/libexec/src/net/http/client.go:250 +0x443
net/http.(*Client).send(0x1602fc0, 0xc00017c000, 0x0, 0x0, 0x0, 0xc00015c028, 0x0, 0x1, 0x136efc0)
	/usr/local/Cellar/go/1.13.6/libexec/src/net/http/client.go:174 +0xfa
net/http.(*Client).do(0x1602fc0, 0xc00017c000, 0x0, 0x0, 0x0)
	/usr/local/Cellar/go/1.13.6/libexec/src/net/http/client.go:641 +0x3ce
net/http.(*Client).Do(...)
	/usr/local/Cellar/go/1.13.6/libexec/src/net/http/client.go:509
net/http.(*Client).Get(0x1602fc0, 0xc00017a000, 0x1d, 0x2, 0x2, 0xc00017a000)
	/usr/local/Cellar/go/1.13.6/libexec/src/net/http/client.go:398 +0xbb
net/http.Get(...)
	/usr/local/Cellar/go/1.13.6/libexec/src/net/http/client.go:370
github.com/NebulousLabs/go-skynet.DownloadFile(0xc0001780c0, 0x53, 0x137e311, 0x10, 0x137a32c, 0x1, 0x137ec6b, 0x12, 0x0, 0x0)
	/Users/marcin/Dropbox/Repos/go-skynet/skynet.go:234 +0x1d8
github.com/NebulousLabs/go-skynet/tests.TestUploadAndDownloadFile(0xc000104100)
	/Users/marcin/Dropbox/Repos/go-skynet/tests/integration_test.go:65 +0x693
testing.tRunner(0xc000104100, 0x1393778)
	/usr/local/Cellar/go/1.13.6/libexec/src/testing/testing.go:909 +0xc9
created by testing.(*T).Run
	/usr/local/Cellar/go/1.13.6/libexec/src/testing/testing.go:960 +0x350
FAIL	github.com/NebulousLabs/go-skynet/tests	0.340s

Custom response function

Instead of Reply(code), use:

gock.New("https://google.com").
  Get("/foo").
  ReplyFunc(func (r *gock.Response) {
    r.StatusCode = 200
    r.Header.Set("foo", "bar")
  })

Parameter matching not working

I got these two gocks in a test suite:

gock.New("http://www.url.com").
    Get("/path/page.php").
    MatchParam("site", "yahoo").
    Persist().
    Reply(200).
    File("testdata/yahoo.html")

gock.New("http://www.url.com").
    Get("/path/page.php").
    MatchParam("site", "google").
    Persist().
    Reply(200).
    File("testdata/google.html")

However, it's always the first gock that takes the requests. What is wrong?

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.