- Enable Quality
- Enable Maintenance
- Enable Validation
- Stub - an object that provides predefined answers to method calls.
- Mock - an object on which you set expectations.
- Fake - an object with limited capabilities (for the purposes of testing), e.g. a fake web service.
Test Double is the general term for stubs, mocks and fakes. A mock is single use, but a fake can be reused.
- Test Fixture - a well known and fixed environment in which tests are run so that results are repeatable. Some people call this the test context.
- Preparation of input data and set-up/creation of fake or mock objects
- Loading a database with a specific, known set of data
- Erasing a hard disk and installing a known clean operating system installation
- Copying a specific known set of files
Test fixtures contribute to setting up the system for the testing process by providing it with all the necessary data for initialization. The setup using fixtures is done to satisfy any preconditions there may be for the code under test. Fixtures allow us to reliably and repeatably create the state our code relies on upon without worrying about the details.
- http://hassansin.github.io/Unit-Testing-http-client-in-Go
- https://blog.bullgare.com/2020/02/a-way-to-test-http-client-in-go/
-
Using
httptest.Server
:httptest.Server
allows us to create a local HTTP server and listen for any requests. When starting, the server chooses any available open port and uses that. So we need to get the URL of the test server and use it instead of the actual service URL. -
Accept a Doer as a parameter The Doer is a single-method interface, as is often the case in Go:
type Doer interface { Do(*http.Request) (*http.Response, error) }
-
By Replacing
http.Transport
: Transport specifies the mechanism by which individual HTTP requests are made. Instead of using the default http.Transport, we’ll replace it with our own implementation. To implement a transport, we’ll have to implement http.RoundTripper interface. From the documentation:func Test_Mine(t *testing.T) { ... client := httpClientWithRoundTripper(http.StatusOK, "OK") ... } type roundTripFunc func(req *http.Request) *http.Response func (f roundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { return f(req), nil } func httpClientWithRoundTripper(statusCode int, response string) *http.Client { return &http.Client{ Transport: roundTripFunc(func(req *http.Request) *http.Response { return &http.Response{ StatusCode: statusCode, Body: ioutil.NopCloser(bytes.NewBufferString(response)), } }), } }
- https://pkg.go.dev/cloud.google.com/go/httpreplay
- https://github.com/SpectoLabs/hoverfly
- https://github.com/google/go-replayers/blob/master/httpreplay/httpreplay.go
- https://github.com/golang/pkgsite/blob/f3da34a449bba5e9ee82f8111c7ed13daeb57824/internal/source/source_test.go#L441
- https://www.calhoun.io/testing-api-libraries/
- https://github.com/joncalhoun/twg/blob/master/stripe/recorder_client_test.go
-
https://github.com/dnaeon/go-vcr ⭐️
-
https://github.com/beme/abide
-
https://github.com/bradleyjkemp/cupaloy snapshot testing in Go
-
https://github.com/seborama/govcr
- https://gist.github.com/efueyo/72611e0ce811f92f7adc96c7b3fe38f6
- https://github.com/tj/go-fixture
- https://github.com/sebdah/goldie
- https://github.com/hexops/autogold
- http://hassansin.github.io/Unit-Testing-http-client-in-Go
- http://www.inanzzz.com/index.php/post/fb0m/mocking-and-testing-http-clients-in-golang
- https://www.thegreatcodeadventure.com/mocking-http-requests-in-golang/
- https://golang.cafe/blog/golang-httptest-example.html
- https://speakerdeck.com/mitchellh/advanced-testing-with-go
- https://building.lang.ai/7-testing-techniques-for-your-golang-codebase-77649a96a1c9
- http://hassansin.github.io/Unit-Testing-http-client-in-Go
- archived Michael Feathers Talk - original
- Michael Feathers Video or https://youtu.be/4fAdXSqG6Bk
- https://understandlegacycode.com/blog/key-points-of-working-effectively-with-legacy-code/
- https://michaelfeathers.typepad.com/michael_feathers_blog/2008/06/the-flawed-theo.html
- https://symflower.com/en/company/blog/2022/better-table-driven-testing/
- https://sendgrid.com/blog/when-writing-unit-tests-dont-use-mocks/
- https://golangforall.com/en/post/dependency-injection.html
- https://scene-si.org/2016/06/16/dependency-injection-patterns-in-go/
- https://betterprogramming.pub/the-3-types-of-dependency-injection-141b40d2cebc
- https://8thlight.com/blog/javier-saldana/2015/02/06/loose-coupling-in-go-lang.html
- https://www.gojek.io/blog/the-many-flavours-of-dependency-injection-in-golang
- https://banzaicloud.com/blog/dependency-injection-go/
- https://www.nerd.vision/post/dependency-injection-in-go
- https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/dependency-injection
- https://kokizzu.blogspot.com/2021/11/alternative-strategy-for-dependency.html
Accepting interfaces, return structs may sound so foreign when you first hear it. However, it can be boiled down to 2 main concepts
- Let the consumer define the interfaces it uses
- Producers should return concrete types