英文:
Mocking a struct field's methods
问题
我正在处理一个简单的 Golang 服务器应用程序,用于进行 OAuth 认证。服务器代码很简单。在进行单元测试时,我需要避免向实际的 OAuth 提供者发出外部 HTTP 请求。
因此,在正常的服务器操作期间,我希望使用真实的调用,而在运行 go test
时,使用模拟方法来阻止外部 HTTP 请求。
我已经创建了 OAuth 方法的模拟,但我不明白如何将它们集成到代码中。通过查看模拟示例,我仍然对如何使用模拟接口感到困惑。
这是原始代码:
type Server struct {
// 这是实际的 golang.org/x/oauth2 Config 结构体
oauth2Config *oauth2.Config
}
func (s *Server) handleCallback() http.HandlerFunc {
// 这是进行外部调用的方法。我想要进行模拟
oauth2Token, err := s.oauth2Config.Exchange(s.context, r.URL.Query().Get("code"))
}
我定义了一个接口和模拟函数:
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
}
我原以为应该修改原始的 Server 结构体以使用新的接口:
- 在正常的服务器操作中,oauth2Config 字段被赋值为
&oath2.Config{}
- 在测试中,oauth2Config 字段被赋值为
&MockOauth2Config{}
type Server struct {
// 改为接口类型
oauth2Config Oauth2ConfigInterface
}
...
oauth2Config: &oauth2.Config{
ClientID: "",
ClientSecret: "",
RedirectURL: "",
Scopes: []string{oidc.ScopeOpenID},
},
但是,当我尝试访问 oauth2Config 的字段时,它给我编译错误。
// 这里会有编译错误
s.verifier = s.provider.Verifier(&oidc.Config{ClientID: s.oauth2Config.ClientID})
一旦 oauth2Config 被声明为接口,我如何访问其字段呢?
或者,我整个模拟的方法都错了吗?
英文:
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?
答案1
得分: 1
回答我自己的问题...
我可能表达得不好,但我确实认为未来的人们会遇到同样的问题。
@bcmills 给出了最好的解决方案:
https://stackoverflow.com/questions/68940230/how-to-mock-net-interface/68941591#68941591
这种方法比使用接口进行模拟要更加优雅,特别是在涉及第三方函数/方法的情况下。
英文:
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:
https://stackoverflow.com/questions/68940230/how-to-mock-net-interface/68941591#68941591
It is far more elegant than mocking using interface. Especially for a case like this where third-party func/methods are involved.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论