You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by GitBox <gi...@apache.org> on 2021/02/05 05:19:49 UTC

[GitHub] [apisix-dashboard] Jaycean commented on a change in pull request #1315: feat: refactor route unit test

Jaycean commented on a change in pull request #1315:
URL: https://github.com/apache/apisix-dashboard/pull/1315#discussion_r570726674



##########
File path: api/internal/handler/route/route_test.go
##########
@@ -14,1743 +14,1421 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package route
 
 import (
 	"encoding/json"
+	"errors"
+	"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"
+	"github.com/apisix/manager-api/internal/utils/consts"
 )
 
-func TestRoute(t *testing.T) {
-	// init
-	err := storage.InitETCDClient(conf.ETCDConfig)
-	assert.Nil(t, err)
-	err = store.InitStores()
-	assert.Nil(t, err)
+type testCase struct {
+	caseDesc     string
+	giveInput    interface{}
+	mockInput    interface{}
+	mockRet      interface{}
+	mockErr      interface{}
+	wantRet      interface{}
+	wantErr      interface{}
+	called       bool
+	serviceInput string
+	scriptRet    interface{}
+	scriptErr    error
+	serviceRet   interface{}
+	serviceErr   error
+	upstreamRet  interface{}
+	upstreamErr  error
+}
 
-	handler := &Handler{
-		routeStore:    store.GetStore(store.HubKeyRoute),
-		svcStore:      store.GetStore(store.HubKeyService),
-		upstreamStore: store.GetStore(store.HubKeyUpstream),
-		scriptStore:   store.GetStore(store.HubKeyScript),
+var DagScript = `
+{
+    "rule":{
+        "root":"451106f8-560c-43a4-acf2-2a6ed0ea57b8",
+        "451106f8-560c-43a4-acf2-2a6ed0ea57b8":[
+            [
+                "code == 403",
+                "b93d622c-92ef-48b4-b6bb-57e1ce893ee3"
+            ],
+            [
+                "",
+                "988ef5c2-c896-4606-a666-3d4cbe24a731"
+            ]
+        ]
+    },
+    "conf":{
+        "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{
+            "name":"uri-blocker",
+            "conf":{
+                "block_rules":[
+                    "root.exe",
+                    "root.m+"
+                ],
+                "rejected_code":403
+            }
+        },
+        "988ef5c2-c896-4606-a666-3d4cbe24a731":{
+            "name":"kafka-logger",
+            "conf":{
+                "batch_max_size":1000,
+                "broker_list":{
+
+                },
+                "buffer_duration":60,
+                "inactive_timeout":5,
+                "include_req_body":false,
+                "kafka_topic":"1",
+                "key":"2",
+                "max_retry_count":0,
+                "name":"kafka logger",
+                "retry_delay":1,
+                "timeout":3
+            }
+        },
+        "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{
+            "name":"fault-injection",
+            "conf":{
+                "abort":{
+                    "body":"200",
+                    "http_status":300
+                },
+                "delay":{
+                    "duration":500
+                }
+            }
+        }
+    },
+    "chart":{
+        "hovered":{
+
+        },
+        "links":{
+            "3a110c30-d6f3-40b1-a8ac-b828cfaa2489":{
+                "from":{
+                    "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
+                    "portId":"port3"
+                },
+                "id":"3a110c30-d6f3-40b1-a8ac-b828cfaa2489",
+                "to":{
+                    "nodeId":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3",
+                    "portId":"port1"
+                }
+            },
+            "c1958993-c1ef-44b1-bb32-7fc6f34870c2":{
+                "from":{
+                    "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
+                    "portId":"port2"
+                },
+                "id":"c1958993-c1ef-44b1-bb32-7fc6f34870c2",
+                "to":{
+                    "nodeId":"988ef5c2-c896-4606-a666-3d4cbe24a731",
+                    "portId":"port1"
+                }
+            },
+            "f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23":{
+                "from":{
+                    "nodeId":"451106f8-560c-43a4-acf2-2a6ed0ea57b8",
+                    "portId":"port2"
+                },
+                "id":"f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23",
+                "to":{
+                    "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
+                    "portId":"port1"
+                }
+            }
+        },
+        "nodes":{
+            "3365eca3-4bc8-4769-bab3-1485dfd6a43c":{
+                "id":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
+                "orientation":0,
+                "ports":{
+                    "port1":{
+                        "id":"port1",
+                        "position":{
+                            "x":107,
+                            "y":0
+                        },
+                        "type":"input"
+                    },
+                    "port2":{
+                        "id":"port2",
+                        "position":{
+                            "x":92,
+                            "y":96
+                        },
+                        "properties":{
+                            "value":"no"
+                        },
+                        "type":"output"
+                    },
+                    "port3":{
+                        "id":"port3",
+                        "position":{
+                            "x":122,
+                            "y":96
+                        },
+                        "properties":{
+                            "value":"yes"
+                        },
+                        "type":"output"
+                    }
+                },
+                "position":{
+                    "x":750.2627969928922,
+                    "y":301.0370335799397
+                },
+                "properties":{
+                    "customData":{
+                        "name":"code == 403",
+                        "type":1
+                    }
+                },
+                "size":{
+                    "height":96,
+                    "width":214
+                },
+                "type":"判断条件"
+            },
+            "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{
+                "id":"451106f8-560c-43a4-acf2-2a6ed0ea57b8",
+                "orientation":0,
+                "ports":{
+                    "port1":{
+                        "id":"port1",
+                        "position":{
+                            "x":100,
+                            "y":0
+                        },
+                        "properties":{
+                            "custom":"property"
+                        },
+                        "type":"input"
+                    },
+                    "port2":{
+                        "id":"port2",
+                        "position":{
+                            "x":100,
+                            "y":96
+                        },
+                        "properties":{
+                            "custom":"property"
+                        },
+                        "type":"output"
+                    }
+                },
+                "position":{
+                    "x":741.5684544145346,
+                    "y":126.75879247285502
+                },
+                "properties":{
+                    "customData":{
+                        "data":{
+                            "block_rules":[
+                                "root.exe",
+                                "root.m+"
+                            ],
+                            "rejected_code":403
+                        },
+                        "name":"uri-blocker",
+                        "type":0
+                    }
+                },
+                "size":{
+                    "height":96,
+                    "width":201
+                },
+                "type":"uri-blocker"
+            },
+            "988ef5c2-c896-4606-a666-3d4cbe24a731":{
+                "id":"988ef5c2-c896-4606-a666-3d4cbe24a731",
+                "orientation":0,
+                "ports":{
+                    "port1":{
+                        "id":"port1",
+                        "position":{
+                            "x":106,
+                            "y":0
+                        },
+                        "properties":{
+                            "custom":"property"
+                        },
+                        "type":"input"
+                    },
+                    "port2":{
+                        "id":"port2",
+                        "position":{
+                            "x":106,
+                            "y":96
+                        },
+                        "properties":{
+                            "custom":"property"
+                        },
+                        "type":"output"
+                    }
+                },
+                "position":{
+                    "x":607.9687500000001,
+                    "y":471.17788461538447
+                },
+                "properties":{
+                    "customData":{
+                        "data":{
+                            "batch_max_size":1000,
+                            "broker_list":{
+
+                            },
+                            "buffer_duration":60,
+                            "inactive_timeout":5,
+                            "include_req_body":false,
+                            "kafka_topic":"1",
+                            "key":"2",
+                            "max_retry_count":0,
+                            "name":"kafka logger",
+                            "retry_delay":1,
+                            "timeout":3
+                        },
+                        "name":"kafka-logger",
+                        "type":0
+                    }
+                },
+                "size":{
+                    "height":96,
+                    "width":212
+                },
+                "type":"kafka-logger"
+            },
+            "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{
+                "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3",
+                "orientation":0,
+                "ports":{
+                    "port1":{
+                        "id":"port1",
+                        "position":{
+                            "x":110,
+                            "y":0
+                        },
+                        "properties":{
+                            "custom":"property"
+                        },
+                        "type":"input"
+                    },
+                    "port2":{
+                        "id":"port2",
+                        "position":{
+                            "x":110,
+                            "y":96
+                        },
+                        "properties":{
+                            "custom":"property"
+                        },
+                        "type":"output"
+                    }
+                },
+                "position":{
+                    "x":988.9074986362261,
+                    "y":478.62041800736495
+                },
+                "properties":{
+                    "customData":{
+                        "data":{
+                            "abort":{
+                                "body":"200",
+                                "http_status":300
+                            },
+                            "delay":{
+                                "duration":500
+                            }
+                        },
+                        "name":"fault-injection",
+                        "type":0
+                    }
+                },
+                "size":{
+                    "height":96,
+                    "width":219
+                },
+                "type":"fault-injection"
+            }
+        },
+        "offset":{
+            "x":-376.83,
+            "y":87.98
+        },
+        "scale":0.832,
+        "selected":{
+            "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3",
+            "type":"node"
+        }
+    }
+}`
+
+func TestRoute_Get(t *testing.T) {
+	tests := []testCase{
+		{
+			caseDesc:  "route: get success",
+			giveInput: &GetInput{ID: "r1"},
+			mockInput: "r1",
+			mockRet: &entity.Route{
+				BaseInfo: entity.BaseInfo{
+					ID: "r1",
+				},
+				URI: "/test",
+			},
+			mockErr: nil,
+			wantRet: &entity.Route{
+				BaseInfo: entity.BaseInfo{
+					ID: "r1",
+				},
+				Script: "script",
+				URI:    "/test",
+			},
+			wantErr:   nil,
+			called:    true,
+			scriptRet: &entity.Script{ID: "r1", Script: "script"},
+			scriptErr: nil,
+		},
+		{
+			caseDesc:  "route: store get failed",
+			giveInput: &GetInput{ID: "failed_key"},
+			mockInput: "failed_key",
+			mockRet:   nil,
+			mockErr:   fmt.Errorf("get failed"),
+			wantRet: &data.SpecCodeResponse{
+				StatusCode: http.StatusNotFound,
+			},
+			wantErr: fmt.Errorf("get failed"),
+			called:  true,
+		},
+		{
+			caseDesc:  "script: store get failed",
+			giveInput: &GetInput{ID: "failed_key"},
+			mockInput: "failed_key",
+			mockRet:   nil,
+			mockErr:   fmt.Errorf("get failed"),
+			wantRet: &data.SpecCodeResponse{
+				StatusCode: http.StatusNotFound,
+			},
+			wantErr:   fmt.Errorf("get failed"),
+			scriptErr: errors.New("get failed"),
+			called:    true,
+		},
 	}
-	assert.NotNil(t, handler)
-
-	//create Note: depends on lib `dag-to-lua` if script exists
-	ctx := droplet.NewContext()
-	route := &entity.Route{}
-	reqBody := `{
-	  "id": "1",
-	  "name": "aaaa",
-	  "uri": "/index.html",
-	  "hosts": ["foo.com", "*.bar.com"],
-	  "vars": [],
-	  "remote_addrs": ["127.0.0.0/8"],
-	  "methods": ["PUT", "GET"],
-	  "status": 1,
-	  "upstream": {
-	      "type": "roundrobin",
-	      "nodes": [{
-	          "host": "www.a.com",
-	          "port": 80,
-	          "weight": 1
-	      }]
-	  },
-	  "script":{
-	      "rule":{
-	          "root":"451106f8-560c-43a4-acf2-2a6ed0ea57b8",
-	          "451106f8-560c-43a4-acf2-2a6ed0ea57b8":[
-	              [
-	                  "code == 403",
-	                  "b93d622c-92ef-48b4-b6bb-57e1ce893ee3"
-	              ],
-	              [
-	                  "",
-	                  "988ef5c2-c896-4606-a666-3d4cbe24a731"
-	              ]
-	          ]
-	      },
-	      "conf":{
-	          "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{
-	              "name":"uri-blocker",
-	              "conf":{
-	                  "block_rules":[
-	                      "root.exe",
-	                      "root.m+"
-	                  ],
-	                  "rejected_code":403
-	              }
-	          },
-	          "988ef5c2-c896-4606-a666-3d4cbe24a731":{
-	              "name":"kafka-logger",
-	              "conf":{
-	                  "batch_max_size":1000,
-	                  "broker_list":{
-	
-	                  },
-	                  "buffer_duration":60,
-	                  "inactive_timeout":5,
-	                  "include_req_body":false,
-	                  "kafka_topic":"1",
-	                  "key":"2",
-	                  "max_retry_count":0,
-	                  "name":"kafka logger",
-	                  "retry_delay":1,
-	                  "timeout":3
-	              }
-	          },
-	          "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{
-	              "name":"fault-injection",
-	              "conf":{
-	                  "abort":{
-	                      "body":"200",
-	                      "http_status":300
-	                  },
-	                  "delay":{
-	                      "duration":500
-	                  }
-	              }
-	          }
-	      },
-	      "chart":{
-	          "hovered":{
-	
-	          },
-	          "links":{
-	              "3a110c30-d6f3-40b1-a8ac-b828cfaa2489":{
-	                  "from":{
-	                      "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
-	                      "portId":"port3"
-	                  },
-	                  "id":"3a110c30-d6f3-40b1-a8ac-b828cfaa2489",
-	                  "to":{
-	                      "nodeId":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3",
-	                      "portId":"port1"
-	                  }
-	              },
-	              "c1958993-c1ef-44b1-bb32-7fc6f34870c2":{
-	                  "from":{
-	                      "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
-	                      "portId":"port2"
-	                  },
-	                  "id":"c1958993-c1ef-44b1-bb32-7fc6f34870c2",
-	                  "to":{
-	                      "nodeId":"988ef5c2-c896-4606-a666-3d4cbe24a731",
-	                      "portId":"port1"
-	                  }
-	              },
-	              "f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23":{
-	                  "from":{
-	                      "nodeId":"451106f8-560c-43a4-acf2-2a6ed0ea57b8",
-	                      "portId":"port2"
-	                  },
-	                  "id":"f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23",
-	                  "to":{
-	                      "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
-	                      "portId":"port1"
-	                  }
-	              }
-	          },
-	          "nodes":{
-	              "3365eca3-4bc8-4769-bab3-1485dfd6a43c":{
-	                  "id":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
-	                  "orientation":0,
-	                  "ports":{
-	                      "port1":{
-	                          "id":"port1",
-	                          "position":{
-	                              "x":107,
-	                              "y":0
-	                          },
-	                          "type":"input"
-	                      },
-	                      "port2":{
-	                          "id":"port2",
-	                          "position":{
-	                              "x":92,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "value":"no"
-	                          },
-	                          "type":"output"
-	                      },
-	                      "port3":{
-	                          "id":"port3",
-	                          "position":{
-	                              "x":122,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "value":"yes"
-	                          },
-	                          "type":"output"
-	                      }
-	                  },
-	                  "position":{
-	                      "x":750.2627969928922,
-	                      "y":301.0370335799397
-	                  },
-	                  "properties":{
-	                      "customData":{
-	                          "name":"code == 403",
-	                          "type":1
-	                      }
-	                  },
-	                  "size":{
-	                      "height":96,
-	                      "width":214
-	                  },
-	                  "type":"判断条件"
-	              },
-	              "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{
-	                  "id":"451106f8-560c-43a4-acf2-2a6ed0ea57b8",
-	                  "orientation":0,
-	                  "ports":{
-	                      "port1":{
-	                          "id":"port1",
-	                          "position":{
-	                              "x":100,
-	                              "y":0
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"input"
-	                      },
-	                      "port2":{
-	                          "id":"port2",
-	                          "position":{
-	                              "x":100,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"output"
-	                      }
-	                  },
-	                  "position":{
-	                      "x":741.5684544145346,
-	                      "y":126.75879247285502
-	                  },
-	                  "properties":{
-	                      "customData":{
-	                          "data":{
-	                              "block_rules":[
-	                                  "root.exe",
-	                                  "root.m+"
-	                              ],
-	                              "rejected_code":403
-	                          },
-	                          "name":"uri-blocker",
-	                          "type":0
-	                      }
-	                  },
-	                  "size":{
-	                      "height":96,
-	                      "width":201
-	                  },
-	                  "type":"uri-blocker"
-	              },
-	              "988ef5c2-c896-4606-a666-3d4cbe24a731":{
-	                  "id":"988ef5c2-c896-4606-a666-3d4cbe24a731",
-	                  "orientation":0,
-	                  "ports":{
-	                      "port1":{
-	                          "id":"port1",
-	                          "position":{
-	                              "x":106,
-	                              "y":0
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"input"
-	                      },
-	                      "port2":{
-	                          "id":"port2",
-	                          "position":{
-	                              "x":106,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"output"
-	                      }
-	                  },
-	                  "position":{
-	                      "x":607.9687500000001,
-	                      "y":471.17788461538447
-	                  },
-	                  "properties":{
-	                      "customData":{
-	                          "data":{
-	                              "batch_max_size":1000,
-	                              "broker_list":{
-	
-	                              },
-	                              "buffer_duration":60,
-	                              "inactive_timeout":5,
-	                              "include_req_body":false,
-	                              "kafka_topic":"1",
-	                              "key":"2",
-	                              "max_retry_count":0,
-	                              "name":"kafka logger",
-	                              "retry_delay":1,
-	                              "timeout":3
-	                          },
-	                          "name":"kafka-logger",
-	                          "type":0
-	                      }
-	                  },
-	                  "size":{
-	                      "height":96,
-	                      "width":212
-	                  },
-	                  "type":"kafka-logger"
-	              },
-	              "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{
-	                  "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3",
-	                  "orientation":0,
-	                  "ports":{
-	                      "port1":{
-	                          "id":"port1",
-	                          "position":{
-	                              "x":110,
-	                              "y":0
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"input"
-	                      },
-	                      "port2":{
-	                          "id":"port2",
-	                          "position":{
-	                              "x":110,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"output"
-	                      }
-	                  },
-	                  "position":{
-	                      "x":988.9074986362261,
-	                      "y":478.62041800736495
-	                  },
-	                  "properties":{
-	                      "customData":{
-	                          "data":{
-	                              "abort":{
-	                                  "body":"200",
-	                                  "http_status":300
-	                              },
-	                              "delay":{
-	                                  "duration":500
-	                              }
-	                          },
-	                          "name":"fault-injection",
-	                          "type":0
-	                      }
-	                  },
-	                  "size":{
-	                      "height":96,
-	                      "width":219
-	                  },
-	                  "type":"fault-injection"
-	              }
-	          },
-	          "offset":{
-	              "x":-376.83,
-	              "y":87.98
-	          },
-	          "scale":0.832,
-	          "selected":{
-	              "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3",
-	              "type":"node"
-	          }
-	      }
-	  }
-	}`
-	err = json.Unmarshal([]byte(reqBody), route)
-	assert.Nil(t, err)
-	ctx.SetInput(route)
-	ret, err := handler.Create(ctx)
-	assert.Nil(t, err)
-	// check the returned valued
-	objRet, ok := ret.(*entity.Route)
-	assert.True(t, ok)
-	assert.Equal(t, "1", objRet.ID)
-
-	//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.Route)
-	assert.Nil(t, err)
-	assert.Equal(t, stored.ID, route.ID)
-
-	//update
-	route2 := &UpdateInput{}
-	route2.ID = "1"
-	reqBody = `{
-	  "id": "1",
-	  "name": "aaaa",
-	  "uri": "/index.html",
-	  "hosts": ["foo.com", "*.bar.com"],
-	  "remote_addrs": ["127.0.0.0/8"],
-	  "methods": ["PUT", "GET"],
-	  "status": 1,
-	  "labels": {
-	      "l1": "v1",
-	      "l2": "v2"
-      },
-	  "upstream": {
-	      "type": "roundrobin",
-	      "nodes": [{
-	          "host": "www.a.com",
-	          "port": 80,
-	          "weight": 1
-	      }]
-	  },
-	  "script":{
-	      "rule":{
-	          "root":"451106f8-560c-43a4-acf2-2a6ed0ea57b8",
-	          "451106f8-560c-43a4-acf2-2a6ed0ea57b8":[
-	              [
-	                  "code == 403",
-	                  "b93d622c-92ef-48b4-b6bb-57e1ce893ee3"
-	              ],
-	              [
-	                  "",
-	                  "988ef5c2-c896-4606-a666-3d4cbe24a731"
-	              ]
-	          ]
-	      },
-	      "conf":{
-	          "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{
-	              "name":"uri-blocker",
-	              "conf":{
-	                  "block_rules":[
-	                      "root.exe",
-	                      "root.m+"
-	                  ],
-	                  "rejected_code":403
-	              }
-	          },
-	          "988ef5c2-c896-4606-a666-3d4cbe24a731":{
-	              "name":"kafka-logger",
-	              "conf":{
-	                  "batch_max_size":1000,
-	                  "broker_list":{
-	
-	                  },
-	                  "buffer_duration":60,
-	                  "inactive_timeout":5,
-	                  "include_req_body":false,
-	                  "kafka_topic":"1",
-	                  "key":"2",
-	                  "max_retry_count":0,
-	                  "name":"kafka logger",
-	                  "retry_delay":1,
-	                  "timeout":3
-	              }
-	          },
-	          "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{
-	              "name":"fault-injection",
-	              "conf":{
-	                  "abort":{
-	                      "body":"200",
-	                      "http_status":300
-	                  },
-	                  "delay":{
-	                      "duration":500
-	                  }
-	              }
-	          }
-	      },
-	      "chart":{
-	          "hovered":{
-	
-	          },
-	          "links":{
-	              "3a110c30-d6f3-40b1-a8ac-b828cfaa2489":{
-	                  "from":{
-	                      "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
-	                      "portId":"port3"
-	                  },
-	                  "id":"3a110c30-d6f3-40b1-a8ac-b828cfaa2489",
-	                  "to":{
-	                      "nodeId":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3",
-	                      "portId":"port1"
-	                  }
-	              },
-	              "c1958993-c1ef-44b1-bb32-7fc6f34870c2":{
-	                  "from":{
-	                      "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
-	                      "portId":"port2"
-	                  },
-	                  "id":"c1958993-c1ef-44b1-bb32-7fc6f34870c2",
-	                  "to":{
-	                      "nodeId":"988ef5c2-c896-4606-a666-3d4cbe24a731",
-	                      "portId":"port1"
-	                  }
-	              },
-	              "f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23":{
-	                  "from":{
-	                      "nodeId":"451106f8-560c-43a4-acf2-2a6ed0ea57b8",
-	                      "portId":"port2"
-	                  },
-	                  "id":"f9c42bf6-c8aa-4e86-8498-8dfbc5c53c23",
-	                  "to":{
-	                      "nodeId":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
-	                      "portId":"port1"
-	                  }
-	              }
-	          },
-	          "nodes":{
-	              "3365eca3-4bc8-4769-bab3-1485dfd6a43c":{
-	                  "id":"3365eca3-4bc8-4769-bab3-1485dfd6a43c",
-	                  "orientation":0,
-	                  "ports":{
-	                      "port1":{
-	                          "id":"port1",
-	                          "position":{
-	                              "x":107,
-	                              "y":0
-	                          },
-	                          "type":"input"
-	                      },
-	                      "port2":{
-	                          "id":"port2",
-	                          "position":{
-	                              "x":92,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "value":"no"
-	                          },
-	                          "type":"output"
-	                      },
-	                      "port3":{
-	                          "id":"port3",
-	                          "position":{
-	                              "x":122,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "value":"yes"
-	                          },
-	                          "type":"output"
-	                      }
-	                  },
-	                  "position":{
-	                      "x":750.2627969928922,
-	                      "y":301.0370335799397
-	                  },
-	                  "properties":{
-	                      "customData":{
-	                          "name":"code == 403",
-	                          "type":1
-	                      }
-	                  },
-	                  "size":{
-	                      "height":96,
-	                      "width":214
-	                  },
-	                  "type":"判断条件"
-	              },
-	              "451106f8-560c-43a4-acf2-2a6ed0ea57b8":{
-	                  "id":"451106f8-560c-43a4-acf2-2a6ed0ea57b8",
-	                  "orientation":0,
-	                  "ports":{
-	                      "port1":{
-	                          "id":"port1",
-	                          "position":{
-	                              "x":100,
-	                              "y":0
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"input"
-	                      },
-	                      "port2":{
-	                          "id":"port2",
-	                          "position":{
-	                              "x":100,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"output"
-	                      }
-	                  },
-	                  "position":{
-	                      "x":741.5684544145346,
-	                      "y":126.75879247285502
-	                  },
-	                  "properties":{
-	                      "customData":{
-	                          "data":{
-	                              "block_rules":[
-	                                  "root.exe",
-	                                  "root.m+"
-	                              ],
-	                              "rejected_code":403
-	                          },
-	                          "name":"uri-blocker",
-	                          "type":0
-	                      }
-	                  },
-	                  "size":{
-	                      "height":96,
-	                      "width":201
-	                  },
-	                  "type":"uri-blocker"
-	              },
-	              "988ef5c2-c896-4606-a666-3d4cbe24a731":{
-	                  "id":"988ef5c2-c896-4606-a666-3d4cbe24a731",
-	                  "orientation":0,
-	                  "ports":{
-	                      "port1":{
-	                          "id":"port1",
-	                          "position":{
-	                              "x":106,
-	                              "y":0
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"input"
-	                      },
-	                      "port2":{
-	                          "id":"port2",
-	                          "position":{
-	                              "x":106,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"output"
-	                      }
-	                  },
-	                  "position":{
-	                      "x":607.9687500000001,
-	                      "y":471.17788461538447
-	                  },
-	                  "properties":{
-	                      "customData":{
-	                          "data":{
-	                              "batch_max_size":1000,
-	                              "broker_list":{
-	
-	                              },
-	                              "buffer_duration":60,
-	                              "inactive_timeout":5,
-	                              "include_req_body":false,
-	                              "kafka_topic":"1",
-	                              "key":"2",
-	                              "max_retry_count":0,
-	                              "name":"kafka logger",
-	                              "retry_delay":1,
-	                              "timeout":3
-	                          },
-	                          "name":"kafka-logger",
-	                          "type":0
-	                      }
-	                  },
-	                  "size":{
-	                      "height":96,
-	                      "width":212
-	                  },
-	                  "type":"kafka-logger"
-	              },
-	              "b93d622c-92ef-48b4-b6bb-57e1ce893ee3":{
-	                  "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3",
-	                  "orientation":0,
-	                  "ports":{
-	                      "port1":{
-	                          "id":"port1",
-	                          "position":{
-	                              "x":110,
-	                              "y":0
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"input"
-	                      },
-	                      "port2":{
-	                          "id":"port2",
-	                          "position":{
-	                              "x":110,
-	                              "y":96
-	                          },
-	                          "properties":{
-	                              "custom":"property"
-	                          },
-	                          "type":"output"
-	                      }
-	                  },
-	                  "position":{
-	                      "x":988.9074986362261,
-	                      "y":478.62041800736495
-	                  },
-	                  "properties":{
-	                      "customData":{
-	                          "data":{
-	                              "abort":{
-	                                  "body":"200",
-	                                  "http_status":300
-	                              },
-	                              "delay":{
-	                                  "duration":500
-	                              }
-	                          },
-	                          "name":"fault-injection",
-	                          "type":0
-	                      }
-	                  },
-	                  "size":{
-	                      "height":96,
-	                      "width":219
-	                  },
-	                  "type":"fault-injection"
-	              }
-	          },
-	          "offset":{
-	              "x":-376.83,
-	              "y":87.98
-	          },
-	          "scale":0.832,
-	          "selected":{
-	              "id":"b93d622c-92ef-48b4-b6bb-57e1ce893ee3",
-	              "type":"node"
-	          }
-	      }
-	  }
-	}`
-
-	err = json.Unmarshal([]byte(reqBody), route2)
-	assert.Nil(t, err)
-	ctx.SetInput(route2)
-	ret, err = handler.Update(ctx)
-	assert.Nil(t, err)
-	// check the returned value
-	objRet, ok = ret.(*entity.Route)
-	assert.True(t, ok)
-	assert.Equal(t, route2.ID, objRet.ID)
-	assert.Equal(t, route2.Labels, objRet.Labels)
-
-	//sleep
-	time.Sleep(time.Duration(100) * time.Millisecond)
-
-	// check ID discrepancy on Update
-
-	// Fail: test the string body id value != string route id value
-	errRoute := &UpdateInput{}
-	errRoute.ID = "2"
-	err = json.Unmarshal([]byte(reqBody), errRoute)
-	assert.Nil(t, err)
-	ctx.SetInput(errRoute)
-	ret, err = handler.Update(ctx)
-	assert.NotNil(t, err)
-	assert.EqualError(t, err, "ID on path (2) doesn't match ID on body (1)")
-	assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode)
-
-	// Fail: tests the float body id value != string route id value
-	reqBodyErr := `{
-		"id": 1,
-		"uri": "/index.html",
-		"upstream": {
-			"type": "roundrobin",
-			"nodes": [{
-				"host": "www.a.com",
-				"port": 80,
-				"weight": 1
-			}]
-		}
-	}`
-	errRoute = &UpdateInput{}
-	errRoute.ID = "2"
-	err = json.Unmarshal([]byte(reqBodyErr), errRoute)
-	assert.Nil(t, err)
-	ctx.SetInput(errRoute)
-	ret, err = handler.Update(ctx)
-	assert.NotNil(t, err)
-	assert.EqualError(t, err, "ID on path (2) doesn't match ID on body (1)")
-	assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode)
-
-	// Success: tests the float body id value is == string route id value
-	reqBodyErr = `{
-		"id": 10,
-		"uri": "/index.html",
-		"upstream": {
-			"type": "roundrobin",
-			"nodes": [{
-				"host": "www.a.com",
-				"port": 80,
-				"weight": 1
-			}]
-		}
-	}`
-	errRoute = &UpdateInput{}
-	errRoute.ID = "10"
-	err = json.Unmarshal([]byte(reqBodyErr), errRoute)
-	assert.Nil(t, err)
-	ctx.SetInput(errRoute)
-	ret, err = handler.Update(ctx)
-	assert.Nil(t, err)
-	// Check the returned value
-	objRet, ok = ret.(*entity.Route)
-	assert.True(t, ok)
-	assert.Equal(t, errRoute.ID, objRet.ID)
-
-	// Success: tests the Body ID can be nil
-	reqBodyErr = `{
-		"uri": "/index.html",
-		"upstream": {
-			"type": "roundrobin",
-			"nodes": [{
-				"host": "www.a.com",
-				"port": 80,
-				"weight": 1
-			}]
-		}
-	}`
-	errRoute = &UpdateInput{}
-	errRoute.ID = "r1"
-	err = json.Unmarshal([]byte(reqBodyErr), errRoute)
-	assert.Nil(t, err)
-	ctx.SetInput(errRoute)
-	ret, err = handler.Update(ctx)
-	assert.Nil(t, err)
-	// Check the returned value
-	objRet, ok = ret.(*entity.Route)
-	assert.True(t, ok)
-	assert.Equal(t, errRoute.ID, objRet.ID)
-
-	//sleep
-	time.Sleep(time.Duration(100) * time.Millisecond)
-
-	//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)
-
-	//list search match
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "name": "a", "uri": "index"}`
-	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)
-
-	//list search name not match
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "name": "not-exists", "uri": "index"}`
-	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), 0)
-
-	//list search uri not match
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "name": "a", "uri": "not-exists"}`
-	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), 0)
-
-	//list search label not match
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "label":"l3"}`
-	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), 0)
-
-	//list search label match
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "label":"l1"}`
-	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)
-
-	//list search label match
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "label":"l1:v1"}`
-	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)
-
-	//list search and label not match
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "label":"l1:v2"}`
-	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), 0)
-
-	// list search and status match
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "status": "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)
-
-	// sleep
-	time.Sleep(time.Duration(100) * time.Millisecond)
-
-	// list search and status not match
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "name": "a", "status": "0"}`
-	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), 0)
-
-	//list search with name and status
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "name": "a", "status": "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)
-
-	//list search with name and label
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "name": "a", "label":"l1:v1"}`
-	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)
-
-	//list search with uri and label
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "uri": "index", "label":"l1:v1"}`
-	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)
-
-	//list search with uri,name and label
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "name": "a", "uri": "index", "label":"l1:v1"}`
-	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)
-
-	//list search with uri,name, status and label
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "name": "a", "status": "1", "uri": "index", "label":"l1:v1"}`
-	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)
 
-	//create route using uris
-	route3 := &entity.Route{}
-	reqBody = `{
-	  "id": "2",
-	  "name": "bbbbb",
-	  "uris": ["/aa", "/bb"],
-	  "hosts": ["foo.com", "*.bar.com"],
-	  "remote_addrs": ["127.0.0.0/8"],
-	  "methods": ["PUT", "GET"],
-	  "upstream": {
-	      "type": "roundrobin",
-	      "nodes": {"www.a.com:80": 1}
-	  }
-	}`
-	err = json.Unmarshal([]byte(reqBody), route3)
-	assert.Nil(t, err)
-	ctx.SetInput(route3)
-	ret, err = handler.Create(ctx)
-	assert.Nil(t, err)
-	objRet, ok = ret.(*entity.Route)
-	assert.True(t, ok)
-	assert.Equal(t, "2", objRet.ID)
+	for _, tc := range tests {
+		getCalled := false
+		mStore := &store.MockInterface{}
+
+		mStore.On("Get", mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
+			getCalled = true
+			assert.Equal(t, tc.mockInput, args.Get(0))
+		}).Return(tc.mockRet, tc.mockErr)
+
+		sStore := &store.MockInterface{}
+		sStore.On("Get", mock.Anything, mock.Anything).Return(tc.scriptRet, tc.scriptErr)
+
+		h := Handler{routeStore: mStore, scriptStore: sStore}
+		ctx := droplet.NewContext()
+		ctx.SetInput(tc.giveInput)
+		ret, err := h.Get(ctx)
+		assert.True(t, tc.called, getCalled)
+		assert.Equal(t, tc.wantRet, ret)
+		assert.Equal(t, tc.wantErr, err)
+	}
+}
 
-	//sleep
-	time.Sleep(time.Duration(100) * time.Millisecond)
+func TestRoute_List(t *testing.T) {
+	mockData := []*entity.Route{
+		{
+			BaseInfo: entity.BaseInfo{CreateTime: 1609742634},
+			Name:     "r1",
+			URI:      "/test_r1",
+			Labels: map[string]string{
+				"version": "v1",
+				"build":   "16",
+			},
+			Upstream: &entity.UpstreamDef{
+				Nodes: []interface{}{
+					map[string]interface{}{
+						"host":   "39.97.63.215",
+						"port":   float64(80),
+						"weight": float64(1),
+					},
+				},
+			},
+		},
+		{
+			BaseInfo: entity.BaseInfo{CreateTime: 1609742635},
+			Name:     "r2",
+			URI:      "/test_r2",
+			Labels: map[string]string{
+				"version": "v1",
+				"build":   "16",
+			},
+		},
+		{
+			BaseInfo: entity.BaseInfo{CreateTime: 1609742636},
+			Name:     "route_test",
+			URI:      "/test_route_test",
+			Labels: map[string]string{
+				"version": "v2",
+				"build":   "17",
+			},
+		},
+		{
+			BaseInfo: entity.BaseInfo{CreateTime: 1609742636},
+			Name:     "test_route",
+			URI:      "/test_test_route",
+			Labels: map[string]string{
+				"version": "v2",
+				"build":   "17",
+				"extra":   "test",
+			},
+		},
+	}
 
-	//list search match uris
-	listInput = &ListInput{}
-	reqBody = `{"page_size": 1, "page": 1, "name": "bbb", "uri": "bb"}`
-	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)
+	tests := []testCase{
+		{
+			caseDesc: "list all route",
+			giveInput: &ListInput{
+				Pagination: store.Pagination{
+					PageSize:   10,
+					PageNumber: 10,
+				},
+			},
+			mockInput: store.ListInput{
+				PageSize:   10,
+				PageNumber: 10,
+			},
+			wantRet: &store.ListOutput{
+				Rows: []interface{}{
+					mockData[0],
+					mockData[1],
+					mockData[2],
+					mockData[3],
+				},
+				TotalSize: 4,
+			},
+			scriptRet: &entity.Script{ID: "r1", Script: "script"},
+			called:    true,
+		},
+		{
+			caseDesc: "list routes with name",
+			giveInput: &ListInput{
+				Name: "route",
+				Pagination: store.Pagination{
+					PageSize:   10,
+					PageNumber: 10,
+				},
+			},
+			mockInput: store.ListInput{
+				PageSize:   10,
+				PageNumber: 10,
+			},
+			wantRet: &store.ListOutput{
+				Rows: []interface{}{
+					mockData[2],
+					mockData[3],
+				},
+				TotalSize: 2,
+			},
+			scriptRet: &entity.Script{ID: "r1", Script: "script"},
+			called:    true,
+		},
+		{
+			caseDesc: "list routes with uri",
+			giveInput: &ListInput{
+				URI: "test_r2",
+				Pagination: store.Pagination{
+					PageSize:   10,
+					PageNumber: 10,
+				},
+			},
+			mockInput: store.ListInput{
+				PageSize:   10,
+				PageNumber: 10,
+			},
+			wantRet: &store.ListOutput{
+				Rows: []interface{}{
+					mockData[1],
+				},
+				TotalSize: 1,
+			},
+			scriptRet: &entity.Script{ID: "r1", Script: "script"},
+			called:    true,
+		},
+		{
+			caseDesc: "list routes with label",
+			giveInput: &ListInput{
+				Label: "version:v1",
+				Pagination: store.Pagination{
+					PageSize:   10,
+					PageNumber: 10,
+				},
+			},
+			mockInput: store.ListInput{
+				PageSize:   10,
+				PageNumber: 10,
+			},
+			wantRet: &store.ListOutput{
+				Rows: []interface{}{
+					mockData[0],
+					mockData[1],
+				},
+				TotalSize: 2,
+			},
+			scriptRet: &entity.Script{ID: "s1", Script: "script"},
+			called:    true,
+		},
+		{
+			caseDesc: "list routes with label",
+			giveInput: &ListInput{
+				Label: "extra",
+				Pagination: store.Pagination{
+					PageSize:   10,
+					PageNumber: 10,
+				},
+			},
+			mockInput: store.ListInput{
+				PageSize:   10,
+				PageNumber: 10,
+			},
+			wantRet: &store.ListOutput{
+				Rows: []interface{}{
+					mockData[3],
+				},
+				TotalSize: 1,
+			},
+			scriptRet: &entity.Script{ID: "s1", Script: "script"},
+			called:    true,
+		},
+		{
+			caseDesc: "list routes and test format",
+			giveInput: &ListInput{
+				Name: "r1",
+				Pagination: store.Pagination{
+					PageSize:   10,
+					PageNumber: 10,
+				},
+			},
+			mockInput: store.ListInput{
+				PageSize:   10,
+				PageNumber: 10,
+			},
+			wantRet: &store.ListOutput{
+				Rows: []interface{}{
+					&entity.Route{
+						BaseInfo: entity.BaseInfo{CreateTime: 1609742634},
+						Name:     "r1",
+						URI:      "/test_r1",
+						Labels: map[string]string{
+							"version": "v1",
+							"build":   "16",
+						},
+						Script: "script",
+						Upstream: &entity.UpstreamDef{
+							Nodes: []*entity.Node{
+								{
+									Host:   "39.97.63.215",
+									Port:   80,
+									Weight: 1,
+								},
+							},
+						},
+					},
+				},
 
-	//delete test data
-	inputDel := &BatchDelete{}
-	reqBody = `{"ids": "1,2"}`
-	err = json.Unmarshal([]byte(reqBody), inputDel)
-	assert.Nil(t, err)
-	ctx.SetInput(inputDel)
-	_, err = handler.BatchDelete(ctx)
-	assert.Nil(t, err)
+				TotalSize: 1,
+			},
+			called: true,
+		},
+	}
 
-	//sleep
-	time.Sleep(time.Duration(100) * time.Millisecond)
+	for _, tc := range tests {
+		t.Run(tc.caseDesc, func(t *testing.T) {
+			getCalled := false
+			mStore := &store.MockInterface{}
+			mStore.On("List", mock.Anything).Run(func(args mock.Arguments) {
+				getCalled = true
+				input := args.Get(0).(store.ListInput)
+				mockInput := tc.mockInput.(store.ListInput)
+				assert.Equal(t, mockInput.PageSize, input.PageSize)
+				assert.Equal(t, mockInput.PageNumber, input.PageNumber)
+			}).Return(func(input store.ListInput) *store.ListOutput {
+				var returnData []interface{}
+				for _, c := range mockData {
+					if input.Predicate(c) {
+						if input.Format == nil {
+							returnData = append(returnData, c)
+							continue
+						}
+
+						returnData = append(returnData, input.Format(c))
+					}
+				}
+
+				return &store.ListOutput{
+					Rows:      returnData,
+					TotalSize: len(returnData),
+				}
+			}, tc.mockErr)
+
+			sStore := &store.MockInterface{}
+			sStore.On("Get", mock.Anything, mock.Anything).Return(tc.scriptRet, tc.scriptErr)
+
+			h := Handler{routeStore: mStore, scriptStore: sStore}
+			ctx := droplet.NewContext()
+			ctx.SetInput(tc.giveInput)
+
+			ret, err := h.List(ctx)
+			assert.Equal(t, tc.called, getCalled)
+			assert.Equal(t, tc.wantRet, ret)
+			assert.Equal(t, tc.wantErr, err)
+		})
+	}
+}
 
-	//get route -- deleted, not found
-	getInput := &GetInput{}
-	reqBody = `{"id": "1"}`
-	err = json.Unmarshal([]byte(reqBody), getInput)
-	assert.Nil(t, err)
-	ctx.SetInput(getInput)
-	ret, err = handler.Get(ctx)
-	assert.EqualError(t, err, "data not found")
-	assert.Equal(t, http.StatusNotFound, ret.(*data.SpecCodeResponse).StatusCode)
+func TestRoute_Create(t *testing.T) {
+	scriptMap := make(map[string]interface{})
 
-	//delete test data
-	reqBody = `{"ids": "not-exists"}`
-	err = json.Unmarshal([]byte(reqBody), inputDel)
+	err := json.Unmarshal([]byte(DagScript), &scriptMap)
 	assert.Nil(t, err)
-	ctx.SetInput(inputDel)
-	ret, err = handler.BatchDelete(ctx)
-	assert.NotNil(t, err)
-	assert.Equal(t, http.StatusNotFound, ret.(*data.SpecCodeResponse).StatusCode)
 
-	//create route with not exist upstream id
-	route4 := &entity.Route{}
-	reqBody = `{
-	  "id": "2222",
-	  "name": "r222",
-	  "uris": ["/aa", "/bb"],
-	  "upstream_id": "not-exists"
-	}`
-	err = json.Unmarshal([]byte(reqBody), route4)
+	luaCode, err := generateLuaCode(scriptMap)
 	assert.Nil(t, err)
-	ctx.SetInput(route4)
-	ret, err = handler.Create(ctx)
-	assert.NotNil(t, err)
-	assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode)
 
-	//type:chash, hash_on: vars, wrong key
-	route5 := &entity.Route{}
-	reqBody = `{
-	  "id": "1",
-	  "methods": ["GET"],
-	  "upstream": {
-	      "nodes": {
-	          "127.0.0.1:8080": 1
-	      },
-	      "type": "chash",
-	      "hash_on":"vars",
-	      "key": "not_support"
-	  },
-	  "desc": "new route",
-	  "uri": "/index.html"
-	}`
-	err = json.Unmarshal([]byte(reqBody), route5)
-	assert.Nil(t, err)
-	ctx.SetInput(route5)
-	ret, err = handler.Create(ctx)
-	assert.NotNil(t, err)
-	assert.Equal(t, http.StatusBadRequest, ret.(*data.SpecCodeResponse).StatusCode)
+	tests := []testCase{
+		{
+			caseDesc: "create route success",
+			giveInput: &entity.Route{
+				BaseInfo: entity.BaseInfo{
+					ID:         "s1",
+					CreateTime: 1609746531,
+				},
+				Name:       "s1",
+				Desc:       "test_route",
+				UpstreamID: "u1",
+				ServiceID:  "s1",
+				Script:     "",
+				Labels: map[string]string{
+					"version": "v1",
+				},
+			},
+			mockInput: &entity.Route{
+				BaseInfo: entity.BaseInfo{
+					ID:         "s1",
+					CreateTime: 1609746531,
+				},
+				Name:       "s1",
+				Desc:       "test_route",
+				UpstreamID: "u1",
+				ServiceID:  "s1",
+				ScriptID:   "s1",
+				Script:     "",
+				Labels: map[string]string{
+					"version": "v1",
+				},
+			},
+			serviceRet:  "service",
+			serviceErr:  nil,
+			upstreamRet: "upstream",
+			upstreamErr: nil,
+			scriptRet:   "script",
+			scriptErr:   nil,
+			wantRet:     nil,

Review comment:
       I have a question: 
   why the wantret nil returned?
   This is not consistent with the interface expectation. 
   Normally, it should return data.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org