httpmock alternatives and similar packages
Based on the "Mock" category.
Alternatively, view httpmock alternatives based on common mentions on social networks and blogs.
-
hoverfly
Lightweight service virtualization/ API simulation / API mocking tool for developers and testers -
smtpmock
SMTP mock server written on Golang. Mimic any 📤 SMTP server behavior for your test environment with fake SMTP server. -
monkey
One line to mock functions/methods/variables in place without dependency injection or code generation
CodeRabbit: AI Code Reviews for Developers
Do you think we are missing an alternative of httpmock or a related project?
Popular Comparisons
README
httpmock
Easy mocking of http responses from external resources.
Install
Currently supports Go 1.9 - 1.19.
v1
branch has to be used instead of master
.
Using go modules (aka. go mod
)
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 last httpmock release, now
.
Note you can use go mod vendor
to vendor your dependencies.
Using $GOPATH
v1
branch is configured as the default branch in github, so:
go get github.com/jarcoal/httpmock
automatically downloads the v1
branch in $GOPATH/src
. Then in your
go files use:
import "github.com/jarcoal/httpmock"
Vendoring, using govendor
for example
When vendoring is used, v1
branch has to be specified. Two choices here:
- preferred way:
govendor fetch github.com/jarcoal/httpmock@v1
then in go files:go import "github.com/jarcoal/httpmock"
- old way (before
v1
was set as default branch), use gopkg to read fromv1
branch:govendor fetch gopkg.in/jarcoal/httpmock.v1
then in go files:go import "gopkg.in/jarcoal/httpmock.v1"
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
},
)
// 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:
http://example.tld/some/path?b=12&a=foo&a=bar
(original URL)http://example.tld/some/path?a=bar&a=foo&b=12
(sorted query params)http://example.tld/some/path
(without query params)/some/path?b=12&a=foo&a=bar
(original URL without scheme and host)/some/path?a=bar&a=foo&b=12
(same, but sorted query params)/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 ...
})
})