【问题标题】:How can I mock Stripe in Go?如何在 Go 中模拟 Stripe?
【发布时间】:2020-06-23 11:47:14
【问题描述】:

我正在尝试模拟 Stripe 进行一些测试。

//testify mock
type Backend struct {
    mock.Mock
}

func (s Backend) Call(method, path, key string, params stripe.ParamsContainer, v interface{}) error {
    args := s.Called(params)
    return args.Error(0)
}

func (s Backend) CallRaw(method, path, key string, body *form.Values, params *stripe.Params, v interface{}) error {
    args := s.Called(params)
    return args.Error(0)
}

func (s Backend) CallMultipart(method, path, key, boundary string, body *bytes.Buffer, params *stripe.Params, v interface{}) error {
    args := s.Called(params)
    return args.Error(0)
}

func (s Backend) SetMaxNetworkRetries(maxNetworkRetries int) {
    s.Called(maxNetworkRetries)
}

然后在测试初始化​​:

//stripe
backend := new(mock.Backend)
backend.On("CallRaw", testify.Anything, testify.Anything, testify.Anything, testify.Anything, testify.Anything).
    Return(nil)
backend.On("Call",
    testify.
        MatchedBy(func(req stripe.ParamsContainer) bool {
            customerParams, ok := req.(*stripe.CustomerParams)
            if ok {
                return *customerParams.Email == "failure@email.com"
            }
            return false
        })).
    Return(fmt.Errorf("downstream stripe error"))
backend.On("Call",
    testify.
        MatchedBy(func(req stripe.ParamsContainer) bool {
            customerParams, ok := req.(*stripe.CustomerParams)
            if ok {
                return *customerParams.Email == "success@email.com"
            }
            return false
        })).
    Return(nil)
sc := &client.API{}
sc.Init("", &stripe.Backends{
    API:     backend,
    Connect: backend,
    Uploads: backend,
})

这行得通 - 但我不知道如何模拟才能真正获得客户?我不想嘲笑client.API。 API代码:https://github.com/stripe/stripe-go/blob/9c5fd87e31fd4a072b4d92571d67437e329dc9db/customer/client.go#L23

还有其他人这样做吗? :)

谢谢

【问题讨论】:

  • 我是 - 但这更多用于单元测试 - 我实际上只是在 Stripe 方法周围实现了一个薄包装......我对这种方法很好。对于功能测试,将使用 stripe-mock。

标签: go stripe-payments testify


【解决方案1】:

这里是 stripe-go v72 的解决方案(部分灵感来自@kozmo 答案)

import (
    "bytes"

    "github.com/stretchr/testify/mock"
    "github.com/stripe/stripe-go/v72"
    "github.com/stripe/stripe-go/v72/form"
)

type stripeBackendMock struct {
    mock.Mock
}

func (s *stripeBackendMock) Call(method, path, key string, params stripe.ParamsContainer, v stripe.LastResponseSetter) error {
    args := s.Called(method, path, key, params, v)
    return args.Error(0)
}

func (s *stripeBackendMock) CallStreaming(method, path, key string, params stripe.ParamsContainer, v stripe.StreamingLastResponseSetter) error {
    args := s.Called(method, path, key, params, v)
    return args.Error(0)
}

func (s *stripeBackendMock) CallRaw(method, path, key string, body *form.Values, params *stripe.Params, v stripe.LastResponseSetter) error {
    args := s.Called(method, path, key, params, v)
    return args.Error(0)
}

func (s *stripeBackendMock) CallMultipart(method, path, key, boundary string, body *bytes.Buffer, params *stripe.Params, v stripe.LastResponseSetter) error {
    args := s.Called(method, path, key, boundary, body, params, v)
    return args.Error(0)
}

func (s *stripeBackendMock) SetMaxNetworkRetries(maxNetworkRetries int64) {
    s.Called(maxNetworkRetries)
}

然后在你的测试中

stripeBackendMock := new(stripeBackendMock)    
stripeTestBackends := &stripe.Backends{
    API: stripeBackendMock,
    Connect: stripeBackendMock,
    Uploads: stripeBackendMock,
}

stripe = client.New("sk_test", stripeTestBackends)
// ...

stripeBackendMock.On("Call", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
    stripeCustomer := args.Get(4).(*stripe.Customer)
    *stripeCustomer = stripe.Customer{ /* mock here */ }
}).Return(nil).Once()
// check stripe.Customers.New(...)

【讨论】:

    【解决方案2】:

    我认为你错误地实现了接口。

    我对@9​​87654321@的认识:

    import (
        "bytes"
        "github.com/stretchr/testify/mock"
        "github.com/stripe/stripe-go/v71"
        "github.com/stripe/stripe-go/v71/form"
    )
    
    type Backend struct {
        mock.Mock
    }
    
    func (s *Backend) Call(method, path, key string, params stripe.ParamsContainer, v stripe.LastResponseSetter) error {
        args := s.Called(method, path, key, params, v)
        return args.Error(0)
    }
    
    func (s *Backend) CallRaw(method, path, key string, body *form.Values, params *stripe.Params, v stripe.LastResponseSetter) error {
        args := s.Called(method, path, key, body, params, v)
        return args.Error(0)
    }
    
    func (s *Backend) CallMultipart(method, path, key, boundary string, body *bytes.Buffer, params *stripe.Params, v stripe.LastResponseSetter) error {
        args := s.Called(method, path, key, boundary, body, params, v)
        return args.Error(0)
    }
    
    func (s *Backend) SetMaxNetworkRetries(maxNetworkRetries int64) {
        s.Called(maxNetworkRetries)
    }
    

    要实现mock,您必须使用指针作为目标func (s *Backend) SetMaxNetworkRetries(maxNetworkRetries int64){...},而不是将目标(func (s Backend) SetMaxNetworkRetries(maxNetworkRetries int64){...}) 复制到方法。

    还必须严格遵守方法签名。

    【讨论】:

      猜你喜欢
      • 2017-11-03
      • 2016-05-08
      • 2016-02-04
      • 2021-12-24
      • 1970-01-01
      • 2021-09-30
      • 1970-01-01
      • 1970-01-01
      • 2010-12-30
      相关资源
      最近更新 更多