gpt4 book ai didi

pointers - 使用指针接收器方法创建包装现有类型的接口(interface)

转载 作者:数据小太阳 更新时间:2023-10-29 03:46:42 26 4
gpt4 key购买 nike

我需要测试一个使用 Google Cloud Pubsub 的应用程序,因此必须包装其类型 pubsub.Clientpubsub.Subscriber 以用于测试目的。然而,尽管进行了几次尝试,我还是无法围绕它们找到一个可以编译的接口(interface)。

我试图包装的方法的定义是:

func (s *Subscription) Receive(
ctx context.Context, f func(context.Context, *Message)) error

func (c *Client) Subscription(id string) *Subscription

这是当前代码。 Receiver 接口(interface)(围绕 Subscriber 的包装器)似乎可以工作,但我怀疑它可能需要更改以修复 SubscriptionMaker,所以我'我们包括两者。

注意:我已经尝试了在何处引用和取消引用指针的几种变体,所以请不要告诉我更改它,除非您解释了为什么建议的配置是正确的或者您已经亲自验证了它编译。

import (
"context"

"cloud.google.com/go/pubsub"
)

type Receiver interface {
Receive(context.Context, func(ctx context.Context, msg *pubsub.Message)) (err error)
}

// Pubsub subscriptions implement Receiver
var _ Receiver = &pubsub.Subscription{}

type SubscriptionMaker interface {
Subscription(name string) (s Receiver)
}

// Pubsub clients implement SubscriptionMaker
var _ SubscriptionMaker = pubsub.Client{}

当前错误信息:

common_types.go:21:5: cannot use "cloud.google.com/go/pubsub".Client literal (type "cloud.google.com/go/pubsub".Client) as type SubscriptionMaker in assignment:
"cloud.google.com/go/pubsub".Client does not implement SubscriptionMaker (wrong type for Subscription method)
have Subscription(string) *"cloud.google.com/go/pubsub".Subscription
want Subscription(string) Receiver

最佳答案

首先,对于大多数用途,使用 ptest package 可能是一种更简单的测试 pubsub 的方法。但是当然,您的具体问题可以适用于任何库,下面的方法可以用于很多事情,而不仅仅是模拟 pubsub


您使用接口(interface)模拟这样的库的更广泛目标是可行的。但是,当您希望模拟的库返回您无法模拟的具体类型(可能是由于未报告的字段)时,情况会很复杂。要采用的方法比通常值得的要复杂得多,因为可能有更简单的方法来测试您的代码。

但如果您打算这样做,您必须采取的方法是不要将整个包包装在接口(interface)中,而不仅仅是您希望模拟的特定方法。

您需要包装任何您希望模拟的类型,这些类型也由您的接口(interface)返回或接受。这通常意味着您还需要修改生产代码(而不仅仅是测试代码),因此这有时可能会破坏现有代码库。

我以前经常这样做的地方是模拟标准库的 sql 驱动程序之类的东西,但同样的方法也可以在这里应用。本质上,您需要为您的 pubsub 库创建一个包装程序包,您甚至可以在生产代码中使用它。同样,这可能对现有代码库造成很大干扰,但为了说明起见。使用您定义的接口(interface):

package mypubsub

import "cloud.google.com/go/pubsub"

type Receiver interface {
Recieve(context.Context, func(context.Context, *pubsub.Message) error)
}

type SubscriptionMaker interface {
Subscription(string) Receiver
}

然后您可以包装默认实现,用于生产代码:

// defaultClient wraps the default pubsub Client functionality.
type defaultClient struct {
*pubsub.Client
}

func (d defaultImplementation) Subscription(name string) Receiver {
return d.Client.Subscription()
}

当然,您需要扩展此包以包装您正在使用的大部分或全部 pubsub 包。这可能有点令人生畏。

但是一旦你这样做了,然后在你的代码中的任何地方使用你的 mypubsub 包,而不是直接依赖于 pubsub 包。现在,您可以在需要测试的任何地方轻松更换模拟实现。

关于pointers - 使用指针接收器方法创建包装现有类型的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56657851/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com