github.com/tencent/goom@v1.0.1/iface.go (about) 1 // Package mocker 定义了 mock 的外层用户使用 API 定义, 2 // 包括函数、方法、接口、未导出函数(或方法的)的 Mocker 的实现。 3 // 当前文件实现了接口 mock 的能力。 4 package mocker 5 6 import ( 7 "fmt" 8 "reflect" 9 "unsafe" 10 11 "github.com/tencent/goom/internal/iface" 12 "github.com/tencent/goom/internal/logger" 13 ) 14 15 // IContext 接口 mock 的接收体 16 // 和 internal/proxy.IContext 保持同步 17 type IContext struct { 18 // Data 可以传递任意数据 19 Data interface{} 20 // 占位属性 21 _ unsafe.Pointer 22 } 23 24 // InterfaceMocker 接口 Mock 25 // 通过生成和替代接口变量实现 Mock 26 type InterfaceMocker interface { 27 ExportedMocker 28 // Method 指定接口方法 29 Method(name string) InterfaceMocker 30 // As 将接口方法应用为函数类型 31 // As 调用之后,请使用 Return 或 When API 的方式来指定 mock 返回。 32 // aFunc 函数的第一个参数必须为*mocker.IContext, 作用是指定接口实现的接收体; 后续的参数原样照抄。 33 As(aFunc interface{}) InterfaceMocker 34 // Inject 将 mock 设置到变量 35 Inject(iFace interface{}) InterfaceMocker 36 } 37 38 // DefaultInterfaceMocker 默认接口 Mocker 39 type DefaultInterfaceMocker struct { 40 *baseMocker 41 ctx *iface.IContext 42 iFace interface{} 43 method string 44 funcDef interface{} 45 } 46 47 // String 接口 Mock 名称 48 func (m *DefaultInterfaceMocker) String() string { 49 t := reflect.TypeOf(m.iFace) 50 if t.Kind() == reflect.Ptr { 51 t = t.Elem() 52 } 53 return fmt.Sprintf("%s.%s", t.String(), m.method) 54 } 55 56 // NewDefaultInterfaceMocker 创建默认接口 Mocker 57 // pkgName 包路径 58 // iFace 接口变量定义 59 func NewDefaultInterfaceMocker(pkgName string, iFace interface{}, ctx *iface.IContext) *DefaultInterfaceMocker { 60 return &DefaultInterfaceMocker{ 61 baseMocker: newBaseMocker(pkgName), 62 ctx: ctx, 63 iFace: iFace, 64 } 65 } 66 67 // Method 指定 mock 的方法名 68 func (m *DefaultInterfaceMocker) Method(name string) InterfaceMocker { 69 if name == "" { 70 panic("method is empty") 71 } 72 m.checkMethod(name) 73 m.method = name 74 return m 75 } 76 77 // checkMethod 检查是否能找到函数 78 func (m *DefaultInterfaceMocker) checkMethod(name string) { 79 sTyp := reflect.TypeOf(m.iFace).Elem() 80 _, ok := sTyp.MethodByName(name) 81 if !ok { 82 panic("method " + name + " not found on " + sTyp.String()) 83 } 84 } 85 86 // Apply 应用接口方法 mock 为实际的接收体方法 87 // callback 函数的第一个参数必须为*mocker.IContext, 作用是指定接口实现的接收体; 后续的参数原样照抄。 88 func (m *DefaultInterfaceMocker) Apply(callback interface{}) { 89 if m.method == "" { 90 panic("method is empty") 91 } 92 m.applyByIFaceMethod(m.ctx, m.iFace, m.method, callback, nil) 93 } 94 95 // As 将接口方法 mock 为实际的接收体方法 96 // aFunc 函数的第一个参数必须为*mocker.IContext, 作用是指定接口实现的接收体; 后续的参数原样照抄。 97 func (m *DefaultInterfaceMocker) As(aFunc interface{}) InterfaceMocker { 98 if m.method == "" { 99 panic("method is empty") 100 } 101 m.funcDef = aFunc 102 return m 103 } 104 105 // When 执行参数匹配时的返回值 106 func (m *DefaultInterfaceMocker) When(specArg ...interface{}) *When { 107 if m.method == "" { 108 panic("method is empty") 109 } 110 if m.when != nil { 111 return m.when.When(specArg...) 112 } 113 114 var ( 115 when *When 116 err error 117 ) 118 if when, err = CreateWhen(m, m.funcDef, specArg, nil, true); err != nil { 119 panic(err) 120 } 121 m.applyByIFaceMethod(m.ctx, m.iFace, m.method, m.funcDef, m.callback) 122 m.when = when 123 return when 124 } 125 126 // Return 指定返回值 127 func (m *DefaultInterfaceMocker) Return(value ...interface{}) *When { 128 if m.funcDef == nil { 129 panic("must use As() API before call Return()") 130 } 131 if m.method == "" { 132 panic("method is empty") 133 } 134 if m.when != nil { 135 return m.when.Return(value...) 136 } 137 138 var ( 139 when *When 140 err error 141 ) 142 if when, err = CreateWhen(m, m.funcDef, nil, value, true); err != nil { 143 panic(err) 144 } 145 m.applyByIFaceMethod(m.ctx, m.iFace, m.method, m.funcDef, m.callback) 146 m.when = when 147 return when 148 } 149 150 // Returns 指定返回多个值 151 func (m *DefaultInterfaceMocker) Returns(values ...interface{}) *When { 152 if m.funcDef == nil { 153 panic("must use As() API before call Return()") 154 } 155 if m.method == "" { 156 panic("method is empty") 157 } 158 if m.when != nil { 159 return m.when.Returns(values...) 160 } 161 162 var ( 163 when *When 164 err error 165 ) 166 if when, err = CreateWhen(m, m.funcDef, nil, nil, true); err != nil { 167 panic(err) 168 } 169 when.Returns(values...) 170 m.applyByIFaceMethod(m.ctx, m.iFace, m.method, m.funcDef, m.callback) 171 m.when = when 172 return when 173 } 174 175 // Origin 回调原函数(暂时不支持) 176 func (m *DefaultInterfaceMocker) Origin(interface{}) ExportedMocker { 177 panic("implement me") 178 } 179 180 // Inject 回调原函数(暂时不支持) 181 func (m *DefaultInterfaceMocker) Inject(interface{}) InterfaceMocker { 182 panic("implement me") 183 } 184 185 // applyByIFaceMethod 根据接口方法应用 mock 186 func (m *DefaultInterfaceMocker) applyByIFaceMethod(ctx *iface.IContext, iFace interface{}, 187 method string, callback interface{}, implV iface.PFunc) { 188 callback, implV = interceptDebugInfo(callback, implV, m) 189 m.baseMocker.applyByIFaceMethod(ctx, iFace, method, callback, implV) 190 logger.Consolefc(logger.DebugLevel, "mocker [%s] apply.", logger.Caller(6), m.String()) 191 }