-
-
Notifications
You must be signed in to change notification settings - Fork 153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inject http.client into httpclient.SendRequest #457
Conversation
- Removed unused getHttpClient function in httpclient.go - Removed httpclient initialisation from sendRequest - inject httpClient into sendRequest, and initialise it using getHttpClient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @Alex-CD .
Thank you for your effort.
Please bear with me, but I would like the following approach.
I suggest that in order to distinguish between net/http.Client and our http.Client we need better naming.
I suggest to prefix the official http.Client with net: netHttpClient
In order to test our code we need our own wrapper of that netHttpClient, that implements an interface, that also has a Spy implementation.
Such as this code would do:
type Client interface {
SendRequest(method string, url string, body []byte) error
}
type HttpClient struct {
netHttpClient *http.Client
}
func CreateHttpClient(disableSSLVerification bool) HttpClient {
return HttpClient{
netHttpClient: GetNetHttpClient(disableSSLVerification),
}
}
func GetNetHttpClient(disableSSLVerification bool) *http.Client {
if disableSSLVerification {
transCfg := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
return &http.Client{Transport: transCfg}
}
return http.DefaultClient
}
type HttpClientSpy struct {
// used in unittests
// records calls to http, but does not send them
}
func CreateHttpClientSpy() HttpClientSpy {
return HttpClientSpy{
// ...
}
}
func (c HttpClient) SendRequest(requestMethod string, requestUrl string, requestBody []byte) error {
say.Info(requestMethod + " " + requestUrl + " " + string(requestBody))
// ...
}
We never ever use the returned responseBody, so I removed that from the return value.
When we run mob in a unittest, we would just use the Spy implementation.
The implementation of our own wrapper (this can be a spy, or the real one) needs to be either passed down the call stack, or stored somewhere.
I dont yet know whats the best option here. Would start with passing it down the call stack.
A Unittest would look something like this (pseudocode):
func TestBreakOf5(t *testing.T) {
_, configuration := setup(t)
httpClient = createHttpClientSpy()
break(httpClient)
httpClientSpy.assertCalledWith("GET", "url", "{the expected json}")
Since these are quite some changes, i propose we do it in small steps.
You would have to undo the parameter injection of netHttpClient.
We don't want any code other than our httpclient package, to depend on netHttpClient.
After you undid the injection, i would already merge.
If you like, you could also start preparing the interface and HttpClient Object.
What are your thoughts on this approach?
I'm fully on board with this approach :) |
@gregorriegler I also see what you mean about the naming being confusing -- to that end I've changed some variable names in what I've added (example) |
e8d2a56
into
remotemobprogramming:main
nice, thank you ! |
This is a tiny change that refactors httpclient to:
getHttpClient
(which was unused).*http.client
intoSendRequest
, rather than havingSendRequest
self-initialise one.SendRequest
initialise ahttp.client
usingGetHttpClient
In terms of logic, things are the same as they were before, with the exception of the request being initialized after the client, instead of before.
Now that
SendRequest
is decoupled fromhttp.DefaultClient
, it's a little easier to write unit tests for it (which I'd be happy to do)I'd be super interested in your thoughts on the general theme of doing dependency injection like this.