I'm working on a simple golang server app that does OAuth authentication. The server code is straight forward. For unit tests, I need to avoid making external HTTP requests to the actual OAuth provider.
So during normal Server operation, I would like to use the real calls, and when running go test
, use a Mock method to prevent external HTTP requests.
I've created mocks of the OAuth methods, but I don't understand the mechanics of how to integrate them into the code. Looking through mock examples, I'm still confused about how a mock interface is used.
Here's the original code:
type Server struct {
//This is the actual golang.org/x/oauth2 Config struct
oauth2Config *oauth2.Config
}
func (s *Server) handleCallback() http.HandlerFunc {
// This is the method that makes external call. I want to mock it
oauth2Token, err := s.oauth2Config.Exchange(s.context, r.URL.Query().Get("code"))
}
I define an interface, and the mock function
type Oauth2ConfigInterface interface {
Exchange(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error)
}
type MockOauth2Config struct {
}
func (o *MockOauth2Config) Exchange(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error) {
return &oauth2.Token{}, nil
}
I would have thought I should change the original Server struct to use the new interface:
- On normal Server operation, oauth2Config field is assigned with &oath2.Config{}
- On tests, oauth2Config field is assigned with &MockOauth2Config{}
type Server struct {
//Changed to interface
oauth2Config Oauth2ConfigInterface
}
...
oauth2Config: &oauth2.Config{
ClientID: "",
ClientSecret: "",
RedirectURL: "",
Scopes: []string{oidc.ScopeOpenID},
},
But when I try to access the fields of oauth2Config, it gives me compile errors.
// compile error here
s.verifier = s.provider.Verifier(&oidc.Config{ClientID: s.oauth2Config.ClientID})
Once oauth2Config has been declared an interface, how can I access the fields?
Or am I doing this whole mock wrong?
CodePudding user response:
Answering my own question...
I may have phrased my question badly but I do think people in the future will run into the same question.
@bcmills gave the best solution: How to mock net.Interface
It is far more elegant than mocking using interface. Especially for a case like this where third-party func/methods are involved.