如何解决了解go中的界面和模拟
我正在尝试为AWS服务(ECR)建立抽象。这是代码:
type ECR struct {
Client ecriface.ECRAPI
Ctx context.Context
}
// ECRCreate establishes aws session and creates a repo with provided input
func (e *ECR) ECRCreate(ecrInput *ecr.CreateRepositoryInput) {
result,err := e.Client.CreateRepositoryWithContext(e.Ctx,ecrInput)
if err != nil {
if aerr,ok := err.(awserr.Error); ok {
switch aerr.Code() {
case ecr.ErrCodeServerException:
log.Errorln(ecr.ErrCodeServerException,aerr.Error())
case ecr.ErrCodeInvalidParameterException:
log.Errorln(ecr.ErrCodeInvalidParameterException,aerr.Error())
case ecr.ErrCodeInvalidTagParameterException:
log.Errorln(ecr.ErrCodeInvalidTagParameterException,aerr.Error())
case ecr.ErrCodeTooManyTagsException:
log.Errorln(ecr.ErrCodeTooManyTagsException,aerr.Error())
case ecr.ErrCodeRepositoryAlreadyExistsException:
log.Errorln(ecr.ErrCodeRepositoryAlreadyExistsException,aerr.Error())
case ecr.ErrCodeLimitExceededException:
log.Errorln(ecr.ErrCodeLimitExceededException,aerr.Error())
case ecr.ErrCodeKmsException:
log.Errorln(ecr.ErrCodeKmsException,aerr.Error())
default:
log.Errorln(aerr.Error())
}
} else {
// Print the error,cast err to awserr.Error to get the Code and
// Message from an error.
log.Errorln(err.Error())
}
return
}
log.Infof("Result: %v",result)
}
要模拟aws sdk,请创建存储库调用:
type mockECRClient struct {
ecriface.ECRAPI
}
func (m *mockECRClient) CreateRepositoryWithContext(ctx aws.Context,input *ecr.CreateRepositoryInput,opts ...request.Option) (*ecr.CreateRepositoryOutput,error) {
createdAt := time.Now()
encryptionType := "AES256"
//awsMockAccount := "974589621236"
encryptConfig := ecr.EncryptionConfiguration{EncryptionType: &encryptionType}
imageScanConfig := input.ImageScanningConfiguration
mockRepo := ecr.Repository{
CreatedAt: &createdAt,EncryptionConfiguration: &encryptConfig,ImageScanningConfiguration: imageScanConfig,}
mockRepoOuput := ecr.CreateRepositoryOutput{Repository: &mockRepo}
return &mockRepoOuput,nil
}
func TestECR_ECRCreate(t *testing.T) {
ctx := context.TODO()
mockSvc := &mockECRClient{}
scan := true
name := "Test1"
inputTest1 := ecr.CreateRepositoryInput{
RepositoryName: &name,ImageScanningConfiguration: &ecr.ImageScanningConfiguration{ScanOnPush: &scan},}
ecrTest := ECR{
mockSvc,ctx,}
ecrTest.ECRCreate(&inputTest1)
}
这有效。但是,我对这里的接口和组合的用法有些困惑。 ECRAPI由ecriface程序包定义,我实现了接口的签名之一,并且仍然能够使用模拟的客户端mockSvc
。
问题:
- 这是如何工作的?这是模仿接口的惯用方式吗?
-
ECRAPI
接口的其他方法呢?那些人如何照顾?
我的理解是正确的,我们可以定义具有任意数量的方法签名的接口,将该接口嵌入到结构中,然后将结构传递到需要接口的任何地方。但这意味着我跳过实现接口的其他签名吗?
我认为我在这里缺少一些重要的概念,请告知!
解决方法
简单的答案是:之所以可行,是因为测试的函数仅调用您显式定义的方法。如果调用其他任何内容,都会失败。
这是怎么回事:
mockECRClient
结构嵌入了接口,因此它具有该接口的所有方法。但是,要调用这些方法中的任何一个,您必须将该接口设置为实现:
x:=mockECRClient{}
x.ECRAPI=<real implementation of ECRAPI>
对x.Func()的调用实际上会调用Func
,在x.Func()中为ECRAPI
定义了x.ECRAPI.Func()
。由于您未设置ECRAPI,因此上面的x.ECRAPI
为nil,并且您调用的使用接收方的任何方法都会惊慌。
但是,您为mockECRClient
定义了一种方法:CreateRepositoryWithContext
。当您调用x.CreateRepositoryWithContext
时,该方法属于x
而不属于x.ECRAPI
,并且接收方为x
,因此可以使用。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。