【问题标题】:Mocking a struct field's methods模拟结构字段的方法
【发布时间】: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/…

标签: go mocking


【解决方案1】:

回答我自己的问题...

我的问题可能表述得很糟糕,但我确实认为未来人们会遇到同样的问题。

@bcmills 给出了最好的解决方案: How to mock net.Interface

它比使用接口模拟要优雅得多。尤其是像这种涉及第三方函数/方法的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    相关资源
    最近更新 更多