package mvc2 import ( "fmt" "reflect" "testing" "github.com/kataras/iris/context" ) type testUserStruct struct { ID int64 Username string } func testBinderFunc(ctx context.Context) testUserStruct { id, _ := ctx.Params().GetInt64("id") username := ctx.Params().Get("username") return testUserStruct{ ID: id, Username: username, } } func TestMakeFuncInputBinder(t *testing.T) { testMakeFuncInputBinder(t, testBinderFunc) } func testMakeFuncInputBinder(t *testing.T, binder interface{}) { b, err := MakeFuncInputBinder(binder) if err != nil { t.Fatalf("failed to make binder: %v", err) } if b == nil { t.Fatalf("excepted non-nil *InputBinder but got nil") } if expected, got := reflect.TypeOf(testUserStruct{}), b.BindType; expected != got { t.Fatalf("expected type of the binder's return value to be: %T but got: %T", expected, got) } expected := testUserStruct{ ID: 42, Username: "kataras", } ctx := context.NewContext(nil) ctx.Params().Set("id", fmt.Sprintf("%v", expected.ID)) ctx.Params().Set("username", expected.Username) ctxValue := []reflect.Value{reflect.ValueOf(ctx)} v := b.BindFunc(ctxValue) if !v.CanInterface() { t.Fatalf("result of binder func cannot be interfaced: %#+v", v) } got, ok := v.Interface().(testUserStruct) if !ok { t.Fatalf("result of binder func should be a type of 'testUserStruct' but got: %#+v", v.Interface()) } if got != expected { t.Fatalf("invalid result of binder func, expected: %v but got: %v", expected, got) } } func testCheck(t *testing.T, testName string, shouldPass bool, errString string) { if shouldPass && errString != "" { t.Fatalf("[%s] %s", testName, errString) } if !shouldPass && errString == "" { t.Fatalf("[%s] expected not to pass", testName) } } // TestGetBindersForInput will test two available binders, one for int // and other for a string, // the first input will contains both of them in the same order, // the second will contain both of them as well but with a different order, // the third will contain only the int input and should fail, // the forth one will contain only the string input and should fail, // the fifth one will contain two integers and should fail, // the last one will contain a struct and should fail, // that no of othe available binders will support it, // so no len of the result should be zero there. func TestGetBindersForInput(t *testing.T) { // binders var ( stringBinder = MustMakeFuncInputBinder(func(ctx context.Context) string { return "a string" }) intBinder = MustMakeFuncInputBinder(func(ctx context.Context) int { return 42 }) ) // in var ( stringType = reflect.TypeOf("string") intType = reflect.TypeOf(1) ) // 1 testCheck(t, "test1", true, testGetBindersForInput(t, []*InputBinder{intBinder, stringBinder}, []interface{}{"a string", 42}, stringType, intType)) availableBinders := []*InputBinder{stringBinder, intBinder} // different order than the fist test. // 2 testCheck(t, "test2", true, testGetBindersForInput(t, availableBinders, []interface{}{"a string", 42}, stringType, intType)) // 3 testCheck(t, "test-3-fail", false, testGetBindersForInput(t, availableBinders, []interface{}{42}, stringType, intType)) // 4 testCheck(t, "test-4-fail", false, testGetBindersForInput(t, availableBinders, []interface{}{"a string"}, stringType, intType)) // 5 testCheck(t, "test-5-fail", false, testGetBindersForInput(t, availableBinders, []interface{}{42, 42}, stringType, intType)) // 6 testCheck(t, "test-6-fail", false, testGetBindersForInput(t, availableBinders, []interface{}{testUserStruct{}}, stringType, intType)) } func testGetBindersForInput(t *testing.T, binders []*InputBinder, expectingResults []interface{}, in ...reflect.Type) (errString string) { m := getBindersForInput(binders, in...) if expected, got := len(expectingResults), len(m); expected != got { return fmt.Sprintf("expected results length(%d) and valid binders length(%d) to be equal, so each input has one binder", expected, got) } ctxValue := []reflect.Value{reflect.ValueOf(context.NewContext(nil))} for idx, expected := range expectingResults { if m[idx] != nil { v := m[idx].BindFunc(ctxValue) if got := v.Interface(); got != expected { return fmt.Sprintf("expected result[%d] to be: %v but got: %v", idx, expected, got) } } else { t.Logf("m[%d] = nil on input = %v\n", idx, expected) } } return "" }