gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/client/mock/mock.go (about) 1 // Package mock provides a mock client for testing 2 package mock 3 4 import ( 5 "context" 6 "fmt" 7 "reflect" 8 "sync" 9 10 "gitee.com/liuxuezhan/go-micro-v1.18.0/client" 11 "gitee.com/liuxuezhan/go-micro-v1.18.0/errors" 12 ) 13 14 var ( 15 _ client.Client = NewClient() 16 ) 17 18 type MockResponse struct { 19 Endpoint string 20 Response interface{} 21 Error error 22 } 23 24 type MockClient struct { 25 Client client.Client 26 Opts client.Options 27 28 sync.Mutex 29 Response map[string][]MockResponse 30 } 31 32 func (m *MockClient) Init(opts ...client.Option) error { 33 m.Lock() 34 defer m.Unlock() 35 36 for _, opt := range opts { 37 opt(&m.Opts) 38 } 39 40 r, ok := fromContext(m.Opts.Context) 41 if !ok { 42 r = make(map[string][]MockResponse) 43 } 44 m.Response = r 45 46 return nil 47 } 48 49 func (m *MockClient) Options() client.Options { 50 return m.Opts 51 } 52 53 func (m *MockClient) NewMessage(topic string, msg interface{}, opts ...client.MessageOption) client.Message { 54 return m.Client.NewMessage(topic, msg, opts...) 55 } 56 57 func (m *MockClient) NewRequest(service, endpoint string, req interface{}, reqOpts ...client.RequestOption) client.Request { 58 return m.Client.NewRequest(service, endpoint, req, reqOpts...) 59 } 60 61 func (m *MockClient) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error { 62 m.Lock() 63 defer m.Unlock() 64 65 response, ok := m.Response[req.Service()] 66 if !ok { 67 return errors.NotFound("go.micro.client.mock", "service not found") 68 } 69 70 for _, r := range response { 71 if r.Endpoint != req.Endpoint() { 72 continue 73 } 74 75 if r.Error != nil { 76 return r.Error 77 } 78 79 v := reflect.ValueOf(rsp) 80 81 if t := reflect.TypeOf(rsp); t.Kind() == reflect.Ptr { 82 v = reflect.Indirect(v) 83 } 84 response := r.Response 85 if t := reflect.TypeOf(r.Response); t.Kind() == reflect.Func { 86 var request []reflect.Value 87 if t.NumIn() == 1 { 88 request = append(request, reflect.ValueOf(req.Body())) 89 } 90 response = reflect.ValueOf(r.Response).Call(request)[0].Interface() 91 } 92 93 v.Set(reflect.ValueOf(response)) 94 95 return nil 96 } 97 98 return fmt.Errorf("rpc: can't find service %s", req.Endpoint()) 99 } 100 101 func (m *MockClient) Stream(ctx context.Context, req client.Request, opts ...client.CallOption) (client.Stream, error) { 102 m.Lock() 103 defer m.Unlock() 104 105 // TODO: mock stream 106 return nil, nil 107 } 108 109 func (m *MockClient) Publish(ctx context.Context, p client.Message, opts ...client.PublishOption) error { 110 return nil 111 } 112 113 func (m *MockClient) String() string { 114 return "mock" 115 } 116 117 func NewClient(opts ...client.Option) *MockClient { 118 options := client.Options{ 119 Context: context.TODO(), 120 } 121 122 for _, opt := range opts { 123 opt(&options) 124 } 125 126 r, ok := fromContext(options.Context) 127 if !ok { 128 r = make(map[string][]MockResponse) 129 } 130 131 return &MockClient{ 132 Client: client.DefaultClient, 133 Opts: options, 134 Response: r, 135 } 136 }