// TestRouter_findRoute 测试路由查找功能
func TestRouter_findRoute(t *testing.T) {
// step1. 构造路由树
testRoutes := []TestNode{
// GET方法路由树
TestNode{
method: http.MethodGet,
path: "/order/detail",
},
TestNode{
method: http.MethodGet,
path: "/",
},
}
r := newRouter()
mockHandleFunc := func(ctx *Context) {}
for _, testRoute := range testRoutes {
r.addRoute(testRoute.method, testRoute.path, mockHandleFunc)
}
// step2. 构造测试用例
testCases := []struct {
name string
method string
path string
isFound bool
matchNode *matchNode
}{
// 测试HTTP动词不存在的用例
{
name: "method not found",
method: http.MethodDelete,
path: "/user",
isFound: false,
matchNode: nil,
},
// 测试完全命中的用例
{
name: "order detail",
method: http.MethodGet,
path: "/order/detail",
isFound: true,
matchNode: &matchNode{
node: &node{
path: "detail",
children: nil,
HandleFunc: mockHandleFunc,
},
},
},
// 测试命中了节点但节点的HandleFunc为nil的情况
{
name: "order",
method: http.MethodGet,
path: "/order",
isFound: true,
matchNode: &matchNode{
node: &node{
path: "order",
children: map[string]*node{
"detail": &node{
path: "detail",
children: nil,
HandleFunc: mockHandleFunc,
},
},
HandleFunc: nil,
},
},
},
// 测试根节点
{
name: "",
method: http.MethodGet,
path: "/",
isFound: true,
matchNode: &matchNode{
node: &node{
path: "/",
children: map[string]*node{
"order": &node{
path: "order",
children: map[string]*node{
"detail": &node{
path: "detail",
children: nil,
HandleFunc: mockHandleFunc,
},
},
HandleFunc: nil,
},
},
HandleFunc: mockHandleFunc,
},
},
},
// 测试路由不存在的用例
{
name: "path not found",
method: http.MethodGet,
path: "/user",
isFound: false,
matchNode: nil,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
foundNode, found := r.findRoute(testCase.method, testCase.path)
// Tips: testCase.isFound是期望的结果,而found是实际的结果
assert.Equal(t, testCase.isFound, found)
// 没有找到路由就不用继续比较了
if !found {
return
}
// 此处和之前的测试一样 不能直接用assert.Equal()比较 因为HandleFunc不可比
// 所以要用封装的node.equal()方法比较
msg, found := testCase.matchNode.node.equal(foundNode.node)
assert.True(t, found, msg)
})
}
}