【发布时间】:2021-09-17 01:52:38
【问题描述】:
我正在开发一个执行 OAuth 身份验证的简单 golang 服务器应用程序。服务器代码是直截了当的。对于单元测试,我需要避免向实际的 OAuth 提供者发出外部 HTTP 请求。
所以在Server正常运行时,我想使用真实调用,而在运行go test时,使用Mock方法来阻止外部HTTP请求。
我创建了 OAuth 方法的模拟,但我不了解如何将它们集成到代码中的机制。浏览 mock 示例,我仍然对如何使用 mock 接口感到困惑。
这是原始代码:
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"))
}
我定义了一个接口,以及模拟函数
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 {
//Changed to interface
oauth2Config Oauth2ConfigInterface
}
...
oauth2Config: &oauth2.Config{
ClientID: "",
ClientSecret: "",
RedirectURL: "",
Scopes: []string{oidc.ScopeOpenID},
},
但是当我尝试访问 oauth2Config 的字段时,它给了我编译错误。
// compile error here
s.verifier = s.provider.Verifier(&oidc.Config{ClientID: s.oauth2Config.ClientID})
一旦 oauth2Config 被声明为接口,我如何访问这些字段?
还是我做错了整个模拟?
【问题讨论】:
-
"当我尝试使用值填充 oauth2Config 结构时" -- 一旦你将
oauth2Config字段更改为Oauth2ConfigInterface它不再是一个结构,它是一个界面。您可以随时初始化配置之前将其分配给oauth2Config字段,甚至在您保留指向它的指针之后,但我假设您已经知道,您能否解释一下停止的原因你不这样做? -
@IssMeftah 谢谢,但在使用任何模拟生成器/框架之前,我想自己做以了解它的机制。
-
你不能模拟具体类型的方法。您只能模拟接口方法(和函数值)。因此,如果您想模拟
oauth2.Config方法,那么您创建接口并使用它而不是具体类型的原始方法是有效的。 -
mock out struct 方法最简单的方法是注入一个函数,而不是直接调用方法;见stackoverflow.com/questions/68940230/how-to-mock-net-interface/…