Skip to content

Commit 65441ad

Browse files
author
Aryan Tikarya
committed
add test for response error and refactor
1 parent 9592989 commit 65441ad

File tree

2 files changed

+234
-10
lines changed

2 files changed

+234
-10
lines changed

handler.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,17 @@ func (e *respError) val(errors *Errors) reflect.Value {
102102

103103
if len(e.Meta) > 0 && v.Type().Implements(marshalableRT) {
104104
_ = v.Interface().(marshalable).UnmarshalJSON(e.Meta)
105-
} else {
106-
msgField := v.Elem().FieldByName("Message")
107-
if msgField.IsValid() && msgField.CanSet() && msgField.Kind() == reflect.String {
108-
msgField.SetString(e.Message)
109-
}
105+
}
106+
107+
msgField := v.Elem().FieldByName("Message")
108+
if msgField.IsValid() && msgField.CanSet() && msgField.Kind() == reflect.String {
109+
msgField.SetString(e.Message)
110+
}
110111

111-
if v.Type().Implements(errorsRT) {
112-
dataField := v.Elem().FieldByName("Data")
113-
if dataField.IsValid() && dataField.CanSet() {
114-
dataField.Set(reflect.ValueOf(e.Data))
115-
}
112+
if v.Type().Implements(errorsRT) {
113+
dataField := v.Elem().FieldByName("Data")
114+
if dataField.IsValid() && dataField.CanSet() {
115+
dataField.Set(reflect.ValueOf(e.Data))
116116
}
117117
}
118118

resp_error_test.go

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
package jsonrpc
2+
3+
import (
4+
"encoding/json"
5+
"reflect"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
// Define the error types
12+
type SimpleError struct {
13+
Message string
14+
}
15+
16+
func (e *SimpleError) Error() string {
17+
return e.Message
18+
}
19+
20+
type DataError struct {
21+
Message string
22+
Data interface{}
23+
}
24+
25+
func (e *DataError) Error() string {
26+
return e.Message
27+
}
28+
29+
func (e *DataError) ErrorData() interface{} {
30+
return e.Data
31+
}
32+
33+
type MetaError struct {
34+
Message string
35+
Details string
36+
}
37+
38+
func (e *MetaError) Error() string {
39+
return e.Message
40+
}
41+
42+
func (e *MetaError) MarshalJSON() ([]byte, error) {
43+
return json.Marshal(struct {
44+
Details string `json:"details"`
45+
}{
46+
Details: e.Details,
47+
})
48+
}
49+
50+
func (e *MetaError) UnmarshalJSON(data []byte) error {
51+
var temp struct {
52+
Details string `json:"details"`
53+
}
54+
if err := json.Unmarshal(data, &temp); err != nil {
55+
return err
56+
}
57+
e.Details = temp.Details
58+
return nil
59+
}
60+
61+
type ComplexError struct {
62+
Message string
63+
Data interface{}
64+
Details string
65+
}
66+
67+
func (e *ComplexError) Error() string {
68+
return e.Message
69+
}
70+
71+
func (e *ComplexError) ErrorData() interface{} {
72+
return e.Data
73+
}
74+
75+
func (e *ComplexError) MarshalJSON() ([]byte, error) {
76+
return json.Marshal(struct {
77+
Message string `json:"message"`
78+
Details string `json:"details"`
79+
Data interface{} `json:"data"`
80+
}{
81+
Details: e.Details,
82+
Message: e.Message,
83+
Data: e.Data,
84+
})
85+
}
86+
87+
func (e *ComplexError) UnmarshalJSON(data []byte) error {
88+
var temp struct {
89+
Message string `json:"message"`
90+
Details string `json:"details"`
91+
Data interface{} `json:"data"`
92+
}
93+
if err := json.Unmarshal(data, &temp); err != nil {
94+
return err
95+
}
96+
e.Details = temp.Details
97+
e.Message = temp.Message
98+
e.Data = temp.Data
99+
return nil
100+
}
101+
102+
func TestRespErrorVal(t *testing.T) {
103+
// Initialize the Errors struct and register error types
104+
errorsMap := NewErrors()
105+
errorsMap.Register(1001, new(*SimpleError))
106+
errorsMap.Register(1002, new(*DataError))
107+
errorsMap.Register(1003, new(*MetaError))
108+
errorsMap.Register(1004, new(*ComplexError))
109+
110+
// Define test cases
111+
testCases := []struct {
112+
name string
113+
respError *respError
114+
expectedType reflect.Type
115+
verify func(err error) error
116+
}{
117+
{
118+
name: "SimpleError",
119+
respError: &respError{
120+
Code: 1001,
121+
Message: "simple error occurred",
122+
},
123+
expectedType: reflect.TypeOf(&SimpleError{}),
124+
verify: func(err error) error {
125+
require.IsType(t, &SimpleError{}, err)
126+
require.Equal(t, "simple error occurred", err.Error())
127+
return nil
128+
},
129+
},
130+
{
131+
name: "DataError",
132+
respError: &respError{
133+
Code: 1002,
134+
Message: "data error occurred",
135+
Data: "additional data",
136+
},
137+
expectedType: reflect.TypeOf(&DataError{}),
138+
verify: func(err error) error {
139+
require.IsType(t, &DataError{}, err)
140+
require.Equal(t, "data error occurred", err.Error())
141+
require.Equal(t, "additional data", err.(*DataError).ErrorData())
142+
return nil
143+
},
144+
},
145+
{
146+
name: "MetaError",
147+
respError: &respError{
148+
Code: 1003,
149+
Message: "meta error occurred",
150+
Meta: func() json.RawMessage {
151+
me := &MetaError{
152+
Details: "meta details",
153+
}
154+
metaData, _ := me.MarshalJSON()
155+
return metaData
156+
}(),
157+
},
158+
expectedType: reflect.TypeOf(&MetaError{}),
159+
verify: func(err error) error {
160+
require.IsType(t, &MetaError{}, err)
161+
require.Equal(t, "meta error occurred", err.Error())
162+
// details will also be included in the error message since it implements the marshable interface
163+
require.Equal(t, "meta details", err.(*MetaError).Details)
164+
return nil
165+
},
166+
},
167+
{
168+
name: "ComplexError",
169+
respError: &respError{
170+
Code: 1004,
171+
Message: "complex error occurred",
172+
Data: "complex data",
173+
Meta: func() json.RawMessage {
174+
ce := &ComplexError{
175+
Details: "complex details",
176+
}
177+
metaData, _ := ce.MarshalJSON()
178+
return metaData
179+
}(),
180+
},
181+
expectedType: reflect.TypeOf(&ComplexError{}),
182+
verify: func(err error) error {
183+
require.IsType(t, &ComplexError{}, err)
184+
require.Equal(t, "complex error occurred", err.Error())
185+
require.Equal(t, "complex data", err.(*ComplexError).ErrorData())
186+
require.Equal(t, "complex details", err.(*ComplexError).Details)
187+
return nil
188+
},
189+
},
190+
{
191+
name: "UnregisteredError",
192+
respError: &respError{
193+
Code: 9999,
194+
Message: "unregistered error occurred",
195+
Data: "some data",
196+
},
197+
expectedType: reflect.TypeOf(&respError{}),
198+
verify: func(err error) error {
199+
require.IsType(t, &respError{}, err)
200+
require.Equal(t, "unregistered error occurred", err.Error())
201+
require.Equal(t, "some data", err.(*respError).ErrorData())
202+
return nil
203+
},
204+
},
205+
}
206+
207+
for _, tc := range testCases {
208+
t.Run(tc.name, func(t *testing.T) {
209+
errValue := tc.respError.val(&errorsMap)
210+
errInterface := errValue.Interface()
211+
err, ok := errInterface.(error)
212+
if !ok {
213+
t.Fatalf("returned value does not implement error interface")
214+
}
215+
216+
if reflect.TypeOf(err) != tc.expectedType {
217+
t.Errorf("expected error type %v, got %v", tc.expectedType, reflect.TypeOf(err))
218+
}
219+
220+
err = tc.verify(err)
221+
require.NoError(t, err, "failed to verify error")
222+
})
223+
}
224+
}

0 commit comments

Comments
 (0)