Skip to content

Commit

Permalink
Merge pull request #129 from tokopedia/support_multi_stub_file
Browse files Browse the repository at this point in the history
feat: support multiple stubs in a file
  • Loading branch information
jekiapp authored Feb 17, 2023
2 parents 2dbe671 + 4dfca9e commit edac53a
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 20 deletions.
7 changes: 7 additions & 0 deletions example/simple/client/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,11 @@ func main() {
log.Fatalf("error from grpc: %v", err)
}
log.Printf("Greeting: %s (return code %d)", r.Message, r.ReturnCode)

name = "world"
r, err = c.SayHello(context.Background(), &pb.Request{Name: name})
if err != nil {
log.Fatalf("error from grpc: %v", err)
}
log.Printf("Greeting: %s (return code %d)", r.Message, r.ReturnCode)
}
39 changes: 28 additions & 11 deletions example/simple/stub/simple.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
{
"service": "Gripmock",
"method": "SayHello",
"input": {
"equals": {
"name": "tokopedia"
[
{
"service": "Gripmock",
"method": "SayHello",
"input": {
"equals": {
"name": "tokopedia"
}
},
"output": {
"data": {
"message": "Hello Tokopedia",
"return_code": 1
}
}
},
"output": {
"data": {
"message": "Hello Tokopedia",
"return_code": 1
{
"service": "Gripmock",
"method": "SayHello",
"input": {
"equals": {
"name": "world"
}
},
"output": {
"data": {
"message": "Hello World",
"return_code": 1
}
}
}
}
]
31 changes: 26 additions & 5 deletions stub/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,21 @@ type storage struct {
}

func storeStub(stub *Stub) error {
return stubStorage.storeStub(stub)
}

func (sm *stubMapping) storeStub(stub *Stub) error {
mx.Lock()
defer mx.Unlock()

strg := storage{
Input: stub.Input,
Output: stub.Output,
}
if stubStorage[stub.Service] == nil {
stubStorage[stub.Service] = make(map[string][]storage)
if (*sm)[stub.Service] == nil {
(*sm)[stub.Service] = make(map[string][]storage)
}
stubStorage[stub.Service][stub.Method] = append(stubStorage[stub.Service][stub.Method], strg)
(*sm)[stub.Service][stub.Method] = append((*sm)[stub.Service][stub.Method], strg)
return nil
}

Expand Down Expand Up @@ -269,6 +273,10 @@ func clearStorage() {
}

func readStubFromFile(path string) {
stubStorage.readStubFromFile(path)
}

func (sm *stubMapping) readStubFromFile(path string) {
files, err := ioutil.ReadDir(path)
if err != nil {
log.Printf("Can't read stub from %s. %v\n", path, err)
Expand All @@ -287,13 +295,26 @@ func readStubFromFile(path string) {
continue
}

if byt[0] == '[' && byt[len(byt)-1] == ']' {
var stubs []*Stub
err = json.Unmarshal(byt, &stubs)
if err != nil {
log.Printf("Error when unmarshalling file %s. %v. skipping...", file.Name(), err)
continue
}
for _, s := range stubs {
sm.storeStub(s)
}
continue
}

stub := new(Stub)
err = json.Unmarshal(byt, stub)
if err != nil {
log.Printf("Error when reading file %s. %v. skipping...", file.Name(), err)
log.Printf("Error when unmarshalling file %s. %v. skipping...", file.Name(), err)
continue
}

storeStub(stub)
sm.storeStub(stub)
}
}
137 changes: 137 additions & 0 deletions stub/storage_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package stub

import (
"encoding/json"
"io/ioutil"
"testing"

"github.com/stretchr/testify/require"
)

func Test_readStubFromFile(t *testing.T) {
tests := []struct {
name string
mock func(service, method string, data []storage) (path string)
service string
method string
data []storage
}{
{
name: "single file, single stub",
mock: func(service, method string, data []storage) (path string) {
dir, err := ioutil.TempDir("", "")
require.NoError(t, err)
tempF, err := ioutil.TempFile(dir, "")
require.NoError(t, err)
defer tempF.Close()

var stubs []Stub
for _, d := range data {
stubs = append(stubs, Stub{
Service: service,
Method: method,
Input: d.Input,
Output: d.Output,
})
}
byt, err := json.Marshal(stubs)
require.NoError(t, err)
_, err = tempF.Write(byt)
require.NoError(t, err)

return dir
},
service: "user",
method: "getname",
data: []storage{
{
Input: Input{Equals: map[string]interface{}{"id": float64(1)}},
Output: Output{Data: map[string]interface{}{"name": "user1"}},
},
},
},
{
name: "single file, multiple stub",
mock: func(service, method string, data []storage) (path string) {
dir, err := ioutil.TempDir("", "")
require.NoError(t, err)
tempF, err := ioutil.TempFile(dir, "")
require.NoError(t, err)
defer tempF.Close()

var stubs []Stub
for _, d := range data {
stubs = append(stubs, Stub{
Service: service,
Method: method,
Input: d.Input,
Output: d.Output,
})
}
byt, err := json.Marshal(stubs)
require.NoError(t, err)
_, err = tempF.Write(byt)
require.NoError(t, err)

return dir
},
service: "user",
method: "getname",
data: []storage{
{
Input: Input{Equals: map[string]interface{}{"id": float64(1)}},
Output: Output{Data: map[string]interface{}{"name": "user1"}},
},
{
Input: Input{Equals: map[string]interface{}{"id": float64(2)}},
Output: Output{Data: map[string]interface{}{"name": "user2"}},
},
},
},
{
name: "multiple file, single stub",
mock: func(service, method string, data []storage) (path string) {
dir, err := ioutil.TempDir("", "")
require.NoError(t, err)

for _, d := range data {
tempF, err := ioutil.TempFile(dir, "")
require.NoError(t, err)
defer tempF.Close()

stub := Stub{
Service: service,
Method: method,
Input: d.Input,
Output: d.Output,
}
byt, err := json.Marshal(stub)
require.NoError(t, err)
_, err = tempF.Write(byt)
require.NoError(t, err)
}

return dir
},
service: "user",
method: "getname",
data: []storage{
{
Input: Input{Equals: map[string]interface{}{"id": float64(1)}},
Output: Output{Data: map[string]interface{}{"name": "user1"}},
},
{
Input: Input{Equals: map[string]interface{}{"id": float64(2)}},
Output: Output{Data: map[string]interface{}{"name": "user2"}},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sm := stubMapping{}
sm.readStubFromFile(tt.mock(tt.service, tt.method, tt.data))
require.ElementsMatch(t, tt.data, sm[tt.service][tt.method])
})
}
}
6 changes: 2 additions & 4 deletions stub/stub_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,15 +284,13 @@ func TestStub(t *testing.T) {
"service":"Testing",
"method":"TestMethod",
"data":{
"field1":"hello field1",
"field2":"hello field2",
"field3":"hello field4"
"field1":"hello field1"
}
}`
return httptest.NewRequest("GET", "/find", bytes.NewReader([]byte(payload)))
},
handler: handleFindStub,
expect: "Can't find stub \n\nService: Testing \n\nMethod: TestMethod \n\nInput\n\n{\n\tfield1: hello field1\n\tfield2: hello field2\n\tfield3: hello field4\n}\n\nClosest Match \n\ncontains:{\n\tfield1: hello field1\n\tfield3: hello field3\n}",
expect: "Can't find stub \n\nService: Testing \n\nMethod: TestMethod \n\nInput\n\n{\n\tfield1: hello field1\n}\n\nClosest Match \n\ncontains:{\n\tfield1: hello field1\n\tfield3: hello field3\n}",
},
{
name: "error find stub equals",
Expand Down

0 comments on commit edac53a

Please sign in to comment.