This is an automated email from the ASF dual-hosted git repository.

starsz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 661e48f  feat: remove the etcd dependency in the service unit test
661e48f is described below

commit 661e48fb8cd1035429bd4d14919f7b8ea910d5ad
Author: Peter Zhu <starsz...@gmail.com>
AuthorDate: Fri Feb 5 12:05:22 2021 +0800

    feat: remove the etcd dependency in the service unit test
---
 api/internal/handler/service/service_test.go | 1037 ++++++++++++++++++++------
 1 file changed, 801 insertions(+), 236 deletions(-)

diff --git a/api/internal/handler/service/service_test.go 
b/api/internal/handler/service/service_test.go
index 4f469af..40da731 100644
--- a/api/internal/handler/service/service_test.go
+++ b/api/internal/handler/service/service_test.go
@@ -18,274 +18,839 @@
 package service
 
 import (
-       "encoding/json"
-       "strings"
+       "fmt"
+       "net/http"
        "testing"
-       "time"
 
        "github.com/shiningrush/droplet"
+       "github.com/shiningrush/droplet/data"
        "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/mock"
 
-       "github.com/apisix/manager-api/internal/conf"
        "github.com/apisix/manager-api/internal/core/entity"
-       "github.com/apisix/manager-api/internal/core/storage"
        "github.com/apisix/manager-api/internal/core/store"
+       "github.com/apisix/manager-api/internal/handler"
 )
 
-func TestService(t *testing.T) {
-       // init
-       err := storage.InitETCDClient(conf.ETCDConfig)
-       assert.Nil(t, err)
-       err = store.InitStores()
-       assert.Nil(t, err)
-
-       handler := &Handler{
-               serviceStore: store.GetStore(store.HubKeyService),
+func TestService_Get(t *testing.T) {
+       tests := []struct {
+               caseDesc   string
+               giveInput  *GetInput
+               giveRet    *entity.Service
+               giveErr    error
+               wantErr    error
+               wantGetKey string
+               wantRet    interface{}
+       }{
+               {
+                       caseDesc:   "normal",
+                       giveInput:  &GetInput{ID: "s1"},
+                       wantGetKey: "s1",
+                       giveRet: &entity.Service{
+                               BaseInfo: entity.BaseInfo{
+                                       ID: "s1",
+                               },
+                               Plugins: map[string]interface{}{
+                                       "limit-count": map[string]interface{}{
+                                               "count":         2,
+                                               "time_window":   60,
+                                               "rejected_code": 503,
+                                               "key":           "remote_addr",
+                                       },
+                               },
+                       },
+                       wantRet: &entity.Service{
+                               BaseInfo: entity.BaseInfo{
+                                       ID: "s1",
+                               },
+                               Plugins: map[string]interface{}{
+                                       "limit-count": map[string]interface{}{
+                                               "count":         2,
+                                               "time_window":   60,
+                                               "rejected_code": 503,
+                                               "key":           "remote_addr",
+                                       },
+                               },
+                       },
+               },
+               {
+                       caseDesc:   "store get failed",
+                       giveInput:  &GetInput{ID: "failed_key"},
+                       wantGetKey: "failed_key",
+                       giveErr:    fmt.Errorf("get failed"),
+                       wantErr:    fmt.Errorf("get failed"),
+                       wantRet: &data.SpecCodeResponse{
+                               StatusCode: http.StatusInternalServerError,
+                       },
+               },
        }
-       assert.NotNil(t, handler)
 
-       //create
-       ctx := droplet.NewContext()
-       service := &entity.Service{}
-       reqBody := `{
-      "id": "1",
-      "plugins": {
-          "limit-count": {
-              "count": 2,
-              "time_window": 60,
-              "rejected_code": 503,
-              "key": "remote_addr"
-          }
-      },
-      "upstream": {
-          "type": "roundrobin",
-          "nodes": [{
-              "host": "39.97.63.215",
-              "port": 80,
-              "weight": 1
-          }]
-      }
-  }`
-       err = json.Unmarshal([]byte(reqBody), service)
-       assert.Nil(t, err)
-       ctx.SetInput(service)
-       ret, err := handler.Create(ctx)
-       assert.Nil(t, err)
-       objRet, ok := ret.(*entity.Service)
-       assert.True(t, ok)
-       assert.Equal(t, "1", objRet.ID)
+       for _, tc := range tests {
+               t.Run(tc.caseDesc, func(t *testing.T) {
+                       getCalled := true
+                       mStore := &store.MockInterface{}
+                       mStore.On("Get", mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                               getCalled = true
+                               assert.Equal(t, tc.wantGetKey, args.Get(0))
+                       }).Return(tc.giveRet, tc.giveErr)
 
-       //sleep
-       time.Sleep(time.Duration(100) * time.Millisecond)
-
-       //get
-       input := &GetInput{}
-       input.ID = "1"
-       ctx.SetInput(input)
-       ret, err = handler.Get(ctx)
-       stored := ret.(*entity.Service)
-       assert.Nil(t, err)
-       assert.Equal(t, stored.ID, service.ID)
+                       h := Handler{serviceStore: mStore}
+                       ctx := droplet.NewContext()
+                       ctx.SetInput(tc.giveInput)
+                       ret, err := h.Get(ctx)
+                       assert.True(t, getCalled)
+                       assert.Equal(t, tc.wantRet, ret)
+                       assert.Equal(t, tc.wantErr, err)
+               })
+       }
+}
 
-       //update
-       service2 := &UpdateInput{}
-       service2.ID = "1"
-       reqBody = `{
-               "name": "test-service",
-               "plugins": {
-                 "limit-count": {
-                     "count": 2,
-                     "time_window": 60,
-                     "rejected_code": 503,
-                     "key": "remote_addr"
-                 }
+func TestService_List(t *testing.T) {
+       tests := []struct {
+               caseDesc  string
+               giveInput *ListInput
+               giveData  []*entity.Service
+               giveErr   error
+               wantErr   error
+               wantInput store.ListInput
+               wantRet   interface{}
+       }{
+               {
+                       caseDesc: "list all service",
+                       giveInput: &ListInput{
+                               Pagination: store.Pagination{
+                                       PageSize:   10,
+                                       PageNumber: 10,
+                               },
+                       },
+                       wantInput: store.ListInput{
+                               PageSize:   10,
+                               PageNumber: 10,
+                       },
+                       giveData: []*entity.Service{
+                               {Name: "s1"},
+                               {Name: "s2"},
+                               {Name: "test_service"},
+                               {Name: "service_test"},
+                       },
+                       wantRet: &store.ListOutput{
+                               Rows: []interface{}{
+                                       &entity.Service{Name: "s1"},
+                                       &entity.Service{Name: "s2"},
+                                       &entity.Service{Name: "test_service"},
+                                       &entity.Service{Name: "service_test"},
+                               },
+                               TotalSize: 4,
+                       },
                },
-               "enable_websocket": true,
-               "upstream": {
-                 "type": "roundrobin",
-                 "nodes": [{
-                     "host": "39.97.63.215",
-                     "port": 80,
-                     "weight": 1
-                 }]
-               }
-       }`
-       err = json.Unmarshal([]byte(reqBody), service2)
-       assert.Nil(t, err)
-       ctx.SetInput(service2)
-       ret, err = handler.Update(ctx)
-       assert.Nil(t, err)
-       // Check the returned value
-       objRet, ok = ret.(*entity.Service)
-       assert.True(t, ok)
-       assert.Equal(t, service2.ID, objRet.ID)
-       assert.Equal(t, service2.Name, objRet.Name)
+               {
+                       caseDesc: "list service with 'service'",
+                       giveInput: &ListInput{
+                               Name: "service",
+                               Pagination: store.Pagination{
+                                       PageSize:   10,
+                                       PageNumber: 10,
+                               },
+                       },
+                       wantInput: store.ListInput{
+                               PageSize:   10,
+                               PageNumber: 10,
+                       },
+                       giveData: []*entity.Service{
+                               {BaseInfo: entity.BaseInfo{CreateTime: 
1609376661}, Name: "s1"},
+                               {BaseInfo: entity.BaseInfo{CreateTime: 
1609376662}, Name: "s2"},
+                               {BaseInfo: entity.BaseInfo{CreateTime: 
1609376663}, Name: "test_service"},
+                               {BaseInfo: entity.BaseInfo{CreateTime: 
1609376664}, Name: "service_test"},
+                       },
+                       wantRet: &store.ListOutput{
+                               Rows: []interface{}{
+                                       &entity.Service{BaseInfo: 
entity.BaseInfo{CreateTime: 1609376663}, Name: "test_service"},
+                                       &entity.Service{BaseInfo: 
entity.BaseInfo{CreateTime: 1609376664}, Name: "service_test"},
+                               },
+                               TotalSize: 2,
+                       },
+               },
+               {
+                       caseDesc: "list service with key s1",
+                       giveInput: &ListInput{
+                               Name: "s1",
+                               Pagination: store.Pagination{
+                                       PageSize:   10,
+                                       PageNumber: 10,
+                               },
+                       },
+                       wantInput: store.ListInput{
+                               PageSize:   10,
+                               PageNumber: 10,
+                       },
+                       giveData: []*entity.Service{
+                               {Name: "s1"},
+                               {Name: "s2"},
+                               {Name: "test_service"},
+                               {Name: "service_test"},
+                       },
+                       wantRet: &store.ListOutput{
+                               Rows: []interface{}{
+                                       &entity.Service{Name: "s1"},
+                               },
+                               TotalSize: 1,
+                       },
+               },
+               {
+                       caseDesc: "list service and format",
+                       giveInput: &ListInput{
+                               Pagination: store.Pagination{
+                                       PageSize:   10,
+                                       PageNumber: 10,
+                               },
+                       },
+                       wantInput: store.ListInput{
+                               PageSize:   10,
+                               PageNumber: 10,
+                       },
+                       giveData: []*entity.Service{
+                               {
+                                       Name: "s1",
+                                       Upstream: &entity.UpstreamDef{
+                                               Nodes: []interface{}{
+                                                       map[string]interface{}{
+                                                               "host":   
"39.97.63.215",
+                                                               "port":   
float64(80),
+                                                               "weight": 
float64(1),
+                                                       },
+                                               },
+                                       },
+                               },
+                               {Name: "s2"},
+                               {Name: "test_service"},
+                               {Name: "service_test"},
+                       },
+                       wantRet: &store.ListOutput{
+                               Rows: []interface{}{
+                                       &entity.Service{Name: "s1", Upstream: 
&entity.UpstreamDef{
+                                               Nodes: []*entity.Node{
+                                                       {
+                                                               Host:   
"39.97.63.215",
+                                                               Port:   80,
+                                                               Weight: 1,
+                                                       },
+                                               },
+                                       }},
+                                       &entity.Service{Name: "s2"},
+                                       &entity.Service{Name: "test_service"},
+                                       &entity.Service{Name: "service_test"},
+                               },
+                               TotalSize: 4,
+                       },
+               },
+       }
 
-       //sleep
-       time.Sleep(time.Duration(100) * time.Millisecond)
+       for _, tc := range tests {
+               t.Run(tc.caseDesc, func(t *testing.T) {
+                       getCalled := true
+                       mStore := &store.MockInterface{}
+                       mStore.On("List", mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                               getCalled = true
+                               input := args.Get(0).(store.ListInput)
+                               assert.Equal(t, tc.wantInput.PageSize, 
input.PageSize)
+                               assert.Equal(t, tc.wantInput.PageNumber, 
input.PageNumber)
+                       }).Return(func(input store.ListInput) *store.ListOutput 
{
+                               var returnData []interface{}
+                               for _, c := range tc.giveData {
+                                       if input.Predicate(c) {
+                                               if input.Format == nil {
+                                                       returnData = 
append(returnData, c)
+                                                       continue
+                                               }
 
-       //list
-       listInput := &ListInput{}
-       reqBody = `{"page_size": 1, "page": 1}`
-       err = json.Unmarshal([]byte(reqBody), listInput)
-       assert.Nil(t, err)
-       ctx.SetInput(listInput)
-       retPage, err := handler.List(ctx)
-       assert.Nil(t, err)
-       dataPage := retPage.(*store.ListOutput)
-       assert.Equal(t, len(dataPage.Rows), 1)
+                                               returnData = append(returnData, 
input.Format(c))
+                                       }
+                               }
+                               return &store.ListOutput{
+                                       Rows:      returnData,
+                                       TotalSize: len(returnData),
+                               }
+                       }, tc.giveErr)
 
-       //list search match
-       listInput2 := &ListInput{}
-       reqBody = `{"page_size": 1, "page": 1, "name": "test"}`
-       err = json.Unmarshal([]byte(reqBody), listInput2)
-       assert.Nil(t, err)
-       ctx.SetInput(listInput2)
-       retPage, err = handler.List(ctx)
-       assert.Nil(t, err)
-       dataPage = retPage.(*store.ListOutput)
-       assert.Equal(t, len(dataPage.Rows), 1)
+                       h := Handler{serviceStore: mStore}
+                       ctx := droplet.NewContext()
+                       ctx.SetInput(tc.giveInput)
+                       ret, err := h.List(ctx)
+                       assert.True(t, getCalled)
+                       assert.Equal(t, tc.wantRet, ret)
+                       assert.Equal(t, tc.wantErr, err)
+               })
+       }
+}
 
-       //list search not match
-       listInput3 := &ListInput{}
-       reqBody = `{"page_size": 1, "page": 1, "name": "not-exists"}`
-       err = json.Unmarshal([]byte(reqBody), listInput3)
-       assert.Nil(t, err)
-       ctx.SetInput(listInput3)
-       retPage, err = handler.List(ctx)
-       assert.Nil(t, err)
-       dataPage = retPage.(*store.ListOutput)
-       assert.Equal(t, len(dataPage.Rows), 0)
+func TestService_Create(t *testing.T) {
+       tests := []struct {
+               caseDesc      string
+               getCalled     bool
+               giveInput     *entity.Service
+               giveRet       interface{}
+               giveErr       error
+               wantInput     *entity.Service
+               wantErr       error
+               wantRet       interface{}
+               upstreamInput string
+               upstreamRet   interface{}
+               upstreamErr   interface{}
+       }{
+               {
+                       caseDesc:  "create success",
+                       getCalled: true,
+                       giveInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       wantInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       upstreamInput: "u1",
+                       upstreamRet: entity.Upstream{
+                               BaseInfo: entity.BaseInfo{
+                                       ID: "u1",
+                               },
+                       },
+               },
+               {
+                       caseDesc:  "create failed, upstream not found",
+                       getCalled: false,
+                       giveInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       wantInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       wantErr:       fmt.Errorf("upstream id: u1 not found"),
+                       wantRet:       &data.SpecCodeResponse{StatusCode: 
http.StatusBadRequest},
+                       upstreamInput: "u1",
+                       upstreamErr:   data.ErrNotFound,
+               },
+               {
+                       caseDesc:  "create failed, upstream return error",
+                       getCalled: false,
+                       giveInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       wantInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       wantErr:       fmt.Errorf("unknown error"),
+                       wantRet:       &data.SpecCodeResponse{StatusCode: 
http.StatusBadRequest},
+                       upstreamInput: "u1",
+                       upstreamErr:   fmt.Errorf("unknown error"),
+               },
+               {
+                       caseDesc:  "create failed, create return error",
+                       getCalled: true,
+                       giveInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       giveErr: fmt.Errorf("create failed"),
+                       wantInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       upstreamInput: "u1",
+                       upstreamRet: entity.Upstream{
+                               BaseInfo: entity.BaseInfo{
+                                       ID: "u1",
+                               },
+                       },
+                       wantErr: fmt.Errorf("create failed"),
+                       wantRet: handler.SpecCodeResponse(fmt.Errorf("create 
failed")),
+               },
+       }
 
-       //delete test data
-       inputDel := &BatchDelete{}
-       reqBody = `{"ids": "1"}`
-       err = json.Unmarshal([]byte(reqBody), inputDel)
-       assert.Nil(t, err)
-       ctx.SetInput(inputDel)
-       _, err = handler.BatchDelete(ctx)
-       assert.Nil(t, err)
+       for _, tc := range tests {
+               t.Run(tc.caseDesc, func(t *testing.T) {
+                       getCalled := false
+                       serviceStore := &store.MockInterface{}
+                       serviceStore.On("Create", mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                               getCalled = true
+                               input := args.Get(1).(*entity.Service)
+                               assert.Equal(t, tc.wantInput, input)
+                       }).Return(tc.giveRet, tc.giveErr)
 
-       //create without upstream
-       service11 := &entity.Service{}
-       reqBody = `{
-      "id": "11",
-      "plugins": {
-          "limit-count": {
-              "count": 2,
-              "time_window": 60,
-              "rejected_code": 503,
-              "key": "remote_addr"
-          }
-      }
-  }`
-       err = json.Unmarshal([]byte(reqBody), service11)
-       assert.Nil(t, err)
-       ctx.SetInput(service11)
-       ret, err = handler.Create(ctx)
-       assert.Nil(t, err)
-       objRet, ok = ret.(*entity.Service)
-       assert.True(t, ok)
-       assert.Equal(t, "11", objRet.ID)
+                       upstreamStore := &store.MockInterface{}
+                       upstreamStore.On("Get", mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                               id := args.Get(0).(string)
+                               assert.Equal(t, tc.upstreamInput, id)
+                       }).Return(tc.upstreamRet, tc.upstreamErr)
 
-       //sleep
-       time.Sleep(time.Duration(100) * time.Millisecond)
+                       h := Handler{serviceStore: serviceStore, upstreamStore: 
upstreamStore}
+                       ctx := droplet.NewContext()
+                       ctx.SetInput(tc.giveInput)
+                       ret, err := h.Create(ctx)
+                       assert.Equal(t, tc.getCalled, getCalled)
+                       assert.Equal(t, tc.wantRet, ret)
+                       assert.Equal(t, tc.wantErr, err)
+               })
+       }
+}
 
-       //get
-       input11 := &GetInput{}
-       input11.ID = "11"
-       ctx.SetInput(input11)
-       ret, err = handler.Get(ctx)
-       stored = ret.(*entity.Service)
-       assert.Nil(t, err)
-       assert.Equal(t, "11", stored.ID)
+func TestService_Update(t *testing.T) {
+       tests := []struct {
+               caseDesc      string
+               getCalled     bool
+               giveInput     *UpdateInput
+               giveErr       error
+               giveRet       interface{}
+               wantInput     *entity.Service
+               wantErr       error
+               wantRet       interface{}
+               upstreamInput string
+               upstreamRet   interface{}
+               upstreamErr   interface{}
+       }{
+               {
+                       caseDesc:  "create success",
+                       getCalled: true,
+                       giveInput: &UpdateInput{
+                               ID: "s1",
+                               Service: entity.Service{
+                                       Name:       "s1",
+                                       UpstreamID: "u1",
+                                       Desc:       "test service",
+                               },
+                       },
+                       wantInput: &entity.Service{
+                               BaseInfo: entity.BaseInfo{
+                                       ID: "s1",
+                               },
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       upstreamInput: "u1",
+                       upstreamRet: entity.Upstream{
+                               BaseInfo: entity.BaseInfo{
+                                       ID: "u1",
+                               },
+                       },
+               },
+               {
+                       caseDesc: "create failed, different id",
+                       giveInput: &UpdateInput{
+                               ID: "s1",
+                               Service: entity.Service{
+                                       BaseInfo: entity.BaseInfo{
+                                               ID: "s2",
+                                       },
+                                       Name:       "s1",
+                                       UpstreamID: "u1",
+                                       Desc:       "test service",
+                               },
+                       },
+                       wantRet: &data.SpecCodeResponse{StatusCode: 
http.StatusBadRequest},
+                       wantErr: fmt.Errorf("ID on path (s1) doesn't match ID 
on body (s2)"),
+               },
+               {
+                       caseDesc: "update failed, upstream not found",
+                       giveInput: &UpdateInput{
+                               ID: "s1",
+                               Service: entity.Service{
+                                       Name:       "s1",
+                                       UpstreamID: "u1",
+                                       Desc:       "test service",
+                               },
+                       },
+                       wantInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       wantErr:       fmt.Errorf("upstream id: u1 not found"),
+                       wantRet:       &data.SpecCodeResponse{StatusCode: 
http.StatusBadRequest},
+                       upstreamInput: "u1",
+                       upstreamErr:   data.ErrNotFound,
+               },
+               {
+                       caseDesc: "update failed, upstream return error",
+                       giveInput: &UpdateInput{
+                               ID: "s1",
+                               Service: entity.Service{
+                                       Name:       "s1",
+                                       UpstreamID: "u1",
+                                       Desc:       "test service",
+                               },
+                       },
+                       wantInput: &entity.Service{
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       wantErr:       fmt.Errorf("unknown error"),
+                       wantRet:       &data.SpecCodeResponse{StatusCode: 
http.StatusBadRequest},
+                       upstreamInput: "u1",
+                       upstreamErr:   fmt.Errorf("unknown error"),
+               },
+               {
+                       caseDesc:  "update failed, update return error",
+                       getCalled: true,
+                       giveInput: &UpdateInput{
+                               ID: "s1",
+                               Service: entity.Service{
+                                       Name:       "s1",
+                                       UpstreamID: "u1",
+                                       Desc:       "test service",
+                               },
+                       },
+                       giveErr:       fmt.Errorf("update failed"),
+                       upstreamInput: "u1",
+                       upstreamRet: entity.Upstream{
+                               BaseInfo: entity.BaseInfo{
+                                       ID: "u1",
+                               },
+                       },
+                       wantInput: &entity.Service{
+                               BaseInfo:   entity.BaseInfo{ID: "s1"},
+                               Name:       "s1",
+                               UpstreamID: "u1",
+                               Desc:       "test service",
+                       },
+                       wantErr: fmt.Errorf("update failed"),
+                       wantRet: handler.SpecCodeResponse(fmt.Errorf("update 
failed")),
+               },
+       }
 
-       //list
-       listInput11 := &ListInput{}
-       reqBody = `{"page_size": 10, "page": 1}`
-       err = json.Unmarshal([]byte(reqBody), listInput11)
-       assert.Nil(t, err)
-       ctx.SetInput(listInput11)
-       _, err = handler.List(ctx)
-       assert.Nil(t, err)
+       for _, tc := range tests {
+               t.Run(tc.caseDesc, func(t *testing.T) {
+                       getCalled := false
+                       serviceStore := &store.MockInterface{}
+                       serviceStore.On("Update", mock.Anything, mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                               getCalled = true
+                               input := args.Get(1).(*entity.Service)
+                               createIfNotExist := args.Get(2).(bool)
+                               assert.Equal(t, tc.wantInput, input)
+                               assert.True(t, createIfNotExist)
+                       }).Return(tc.giveRet, tc.giveErr)
 
-       //delete test data
-       inputDel11 := &BatchDelete{}
-       reqBody = `{"ids": "11"}`
-       err = json.Unmarshal([]byte(reqBody), inputDel11)
-       assert.Nil(t, err)
-       ctx.SetInput(inputDel11)
-       _, err = handler.BatchDelete(ctx)
-       assert.Nil(t, err)
+                       upstreamStore := &store.MockInterface{}
+                       upstreamStore.On("Get", mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                               id := args.Get(0).(string)
+                               assert.Equal(t, tc.upstreamInput, id)
+                       }).Return(tc.upstreamRet, tc.upstreamErr)
 
+                       h := Handler{serviceStore: serviceStore, upstreamStore: 
upstreamStore}
+                       ctx := droplet.NewContext()
+                       ctx.SetInput(tc.giveInput)
+                       ret, err := h.Update(ctx)
+                       assert.Equal(t, tc.getCalled, getCalled)
+                       assert.Equal(t, tc.wantRet, ret)
+                       assert.Equal(t, tc.wantErr, err)
+               })
+       }
 }
 
-func TestService_Patch_Update(t *testing.T) {
-       //create
-       handler := &Handler{
-               serviceStore: store.GetStore(store.HubKeyService),
+func TestService_Patch(t *testing.T) {
+       existService := &entity.Service{
+               BaseInfo: entity.BaseInfo{
+                       ID:         "s1",
+                       CreateTime: 1609340491,
+                       UpdateTime: 1609340491,
+               },
+               Name:            "exist_service",
+               UpstreamID:      "u1",
+               EnableWebsocket: false,
+               Labels: map[string]string{
+                       "version": "v1",
+               },
+               Plugins: map[string]interface{}{
+                       "limit-count": map[string]interface{}{
+                               "count":         2,
+                               "time_window":   60,
+                               "rejected_code": 503,
+                               "key":           "remote_addr",
+                       },
+               },
+       }
+
+       tests := []struct {
+               caseDesc     string
+               giveInput    *PatchInput
+               giveErr      error
+               giveRet      interface{}
+               wantInput    *entity.Service
+               wantErr      error
+               wantRet      interface{}
+               serviceInput string
+               serviceRet   *entity.Service
+               serviceErr   error
+               called       bool
+       }{
+               {
+                       caseDesc: "patch all success",
+                       giveInput: &PatchInput{
+                               ID:      "s1",
+                               SubPath: "",
+                               Body: []byte(`{
+                                               "name":"patched",
+                                               "upstream_id":"u2",
+                                               "enable_websocket":true,
+                                               "labels":{
+                                                       "version":"v1",
+                                                       "build":"16"
+                                               },
+                                               "plugins":{
+                                                       "limit-count":{
+                                                               "count":2,
+                                                               
"time_window":60,
+                                                               
"rejected_code": 504,
+                                                               
"key":"remote_addr"
+                                                       },
+                                                       "key-auth":{
+                                                               "key":"auth-one"
+                                                       }
+                                               }
+                                       }`),
+                       },
+                       wantInput: &entity.Service{
+                               BaseInfo: entity.BaseInfo{
+                                       ID:         "s1",
+                                       CreateTime: 1609340491,
+                                       UpdateTime: 1609340491,
+                               },
+                               Name:            "patched",
+                               UpstreamID:      "u2",
+                               EnableWebsocket: true,
+                               Labels: map[string]string{
+                                       "version": "v1",
+                                       "build":   "16",
+                               },
+                               Plugins: map[string]interface{}{
+                                       "limit-count": map[string]interface{}{
+                                               "count":         float64(2),
+                                               "time_window":   float64(60),
+                                               "rejected_code": float64(504),
+                                               "key":           "remote_addr",
+                                       },
+                                       "key-auth": map[string]interface{}{
+                                               "key": "auth-one",
+                                       },
+                               },
+                       },
+                       serviceInput: "s1",
+                       serviceRet:   existService,
+                       called:       true,
+               },
+               {
+                       caseDesc: "patch part of service success",
+                       giveInput: &PatchInput{
+                               ID:      "s1",
+                               SubPath: "",
+                               Body: []byte(`{
+                                               "name":"patched",
+                                               "upstream_id":"u2",
+                                               "enable_websocket":true,
+                                               "labels":{
+                                                       "version":"v1",
+                                                       "build":"16"
+                                               }
+                                       }`),
+                       },
+                       wantInput: &entity.Service{
+                               BaseInfo: entity.BaseInfo{
+                                       ID:         "s1",
+                                       CreateTime: 1609340491,
+                                       UpdateTime: 1609340491,
+                               },
+                               Name:            "patched",
+                               UpstreamID:      "u2",
+                               EnableWebsocket: true,
+                               Labels: map[string]string{
+                                       "version": "v1",
+                                       "build":   "16",
+                               },
+                               Plugins: map[string]interface{}{
+                                       "limit-count": map[string]interface{}{
+                                               "count":         float64(2),
+                                               "time_window":   float64(60),
+                                               "rejected_code": float64(503),
+                                               "key":           "remote_addr",
+                                       },
+                               },
+                       },
+                       serviceInput: "s1",
+                       serviceRet:   existService,
+                       called:       true,
+               },
+               {
+                       caseDesc: "patch name success with sub path",
+                       giveInput: &PatchInput{
+                               ID:      "s1",
+                               SubPath: "/upstream_id",
+                               Body:    []byte(`{"upstream_id":"u3"}`),
+                       },
+                       wantInput: &entity.Service{
+                               BaseInfo: entity.BaseInfo{
+                                       ID:         "s1",
+                                       CreateTime: 1609340491,
+                                       UpdateTime: 1609340491,
+                               },
+                               Name: "exist_service",
+                               UpstreamID: map[string]interface{}{
+                                       "upstream_id": "u3",
+                               },
+                               EnableWebsocket: false,
+                               Labels: map[string]string{
+                                       "version": "v1",
+                               },
+                               Plugins: map[string]interface{}{
+                                       "limit-count": map[string]interface{}{
+                                               "count":         float64(2),
+                                               "time_window":   float64(60),
+                                               "rejected_code": float64(503),
+                                               "key":           "remote_addr",
+                                       },
+                               },
+                       },
+                       serviceInput: "s1",
+                       serviceRet:   existService,
+                       called:       true,
+               },
+               {
+                       caseDesc: "patch labels success",
+                       giveInput: &PatchInput{
+                               ID:      "s1",
+                               SubPath: "/labels",
+                               Body:    []byte(`{"version": "v3"}`),
+                       },
+                       wantInput: &entity.Service{
+                               BaseInfo: entity.BaseInfo{
+                                       ID:         "s1",
+                                       CreateTime: 1609340491,
+                                       UpdateTime: 1609340491,
+                               },
+                               Name:            "exist_service",
+                               EnableWebsocket: false,
+                               Labels: map[string]string{
+                                       "version": "v3",
+                               },
+                               UpstreamID: "u1",
+                               Plugins: map[string]interface{}{
+                                       "limit-count": map[string]interface{}{
+                                               "count":         float64(2),
+                                               "time_window":   float64(60),
+                                               "rejected_code": float64(503),
+                                               "key":           "remote_addr",
+                                       },
+                               },
+                       },
+                       serviceInput: "s1",
+                       serviceRet:   existService,
+                       called:       true,
+               },
+               {
+                       caseDesc: "patch failed, service store get error",
+                       giveInput: &PatchInput{
+                               ID:   "s1",
+                               Body: []byte{},
+                       },
+                       serviceInput: "s1",
+                       serviceErr:   fmt.Errorf("get error"),
+                       wantRet:      handler.SpecCodeResponse(fmt.Errorf("get 
error")),
+                       wantErr:      fmt.Errorf("get error"),
+                       called:       false,
+               },
        }
-       ctx := droplet.NewContext()
-       service := &entity.Service{}
-       reqBody := `{
-               "id": "3",
-               "name": "testservice",
-               "upstream": {
-                       "type": "roundrobin",
-                       "nodes": [{
-                               "host": "172.16.238.20",
-                               "port": 1980,
-                               "weight": 1
-                       }]
-               }
-       }`
-       err := json.Unmarshal([]byte(reqBody), service)
-       assert.Nil(t, err)
-       ctx.SetInput(service)
-       ret, err := handler.Create(ctx)
-       assert.Nil(t, err)
-       objRet, ok := ret.(*entity.Service)
-       assert.True(t, ok)
-       assert.Equal(t, "3", objRet.ID)
 
-       //sleep
-       time.Sleep(time.Duration(20) * time.Millisecond)
+       for _, tc := range tests {
+               t.Run(tc.caseDesc, func(t *testing.T) {
+                       getCalled := false
+                       serviceStore := &store.MockInterface{}
+                       serviceStore.On("Update", mock.Anything, mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                               getCalled = true
+                               input := args.Get(1).(*entity.Service)
+                               createIfNotExist := args.Get(2).(bool)
+                               assert.Equal(t, tc.wantInput, input)
+                               assert.False(t, createIfNotExist)
+                       }).Return(tc.giveRet, tc.giveErr)
 
-       reqBody1 := `{
-               "id": "3",
-               "name": "testpatch",
-               "upstream": {
-                       "type": "roundrobin",
-                       "nodes": [{
-                               "host": "172.16.238.20",
-                               "port": 1981,
-                               "weight": 1
-                       }]
-               }
-       }`
-       responesBody := 
`"nodes":[{"host":"172.16.238.20","port":1981,"weight":1}],"type":"roundrobin"}`
+                       serviceStore.On("Get", mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                               input := args.Get(0).(string)
+                               assert.Equal(t, tc.serviceInput, input)
+                       }).Return(tc.serviceRet, tc.serviceErr)
 
-       input2 := &PatchInput{}
-       input2.ID = "3"
-       input2.SubPath = ""
-       input2.Body = []byte(reqBody1)
-       ctx.SetInput(input2)
+                       h := Handler{serviceStore: serviceStore}
+                       ctx := droplet.NewContext()
+                       ctx.SetInput(tc.giveInput)
+                       ret, err := h.Patch(ctx)
+                       assert.Equal(t, tc.called, getCalled)
+                       assert.Equal(t, tc.wantRet, ret)
+                       assert.Equal(t, tc.wantErr, err)
+               })
+       }
+}
 
-       ret2, err := handler.Patch(ctx)
-       assert.Nil(t, err)
-       _ret2, err := json.Marshal(ret2)
-       assert.Nil(t, err)
-       isContains := strings.Contains(string(_ret2), responesBody)
-       assert.True(t, isContains)
+func TestServices_Delete(t *testing.T) {
+       tests := []struct {
+               caseDesc  string
+               giveInput *BatchDelete
+               giveErr   error
+               wantInput []string
+               wantErr   error
+               wantRet   interface{}
+       }{
+               {
+                       caseDesc: "delete success",
+                       giveInput: &BatchDelete{
+                               IDs: "s1",
+                       },
+                       wantInput: []string{"s1"},
+               },
+               {
+                       caseDesc: "batch delete success",
+                       giveInput: &BatchDelete{
+                               IDs: "s1,s2",
+                       },
+                       wantInput: []string{"s1", "s2"},
+               },
+               {
+                       caseDesc: "delete failed",
+                       giveInput: &BatchDelete{
+                               IDs: "s1",
+                       },
+                       giveErr:   fmt.Errorf("delete error"),
+                       wantInput: []string{"s1"},
+                       wantRet:   handler.SpecCodeResponse(fmt.Errorf("delete 
error")),
+                       wantErr:   fmt.Errorf("delete error"),
+               },
+       }
 
-       //delete test data
-       inputDel2 := &BatchDelete{}
-       reqBody = `{"ids": "3"}`
-       err = json.Unmarshal([]byte(reqBody), inputDel2)
-       assert.Nil(t, err)
-       ctx.SetInput(inputDel2)
-       _, err = handler.BatchDelete(ctx)
-       assert.Nil(t, err)
+       for _, tc := range tests {
+               t.Run(tc.caseDesc, func(t *testing.T) {
+                       getCalled := false
+                       serviceStore := &store.MockInterface{}
+                       serviceStore.On("BatchDelete", mock.Anything, 
mock.Anything).Run(func(args mock.Arguments) {
+                               getCalled = true
+                               input := args.Get(1).([]string)
+                               assert.Equal(t, tc.wantInput, input)
+                       }).Return(tc.giveErr)
 
+                       h := Handler{serviceStore: serviceStore}
+                       ctx := droplet.NewContext()
+                       ctx.SetInput(tc.giveInput)
+                       ret, err := h.BatchDelete(ctx)
+                       assert.True(t, getCalled)
+                       assert.Equal(t, tc.wantRet, ret)
+                       assert.Equal(t, tc.wantErr, err)
+               })
+       }
 }
-

Reply via email to