func performValidationTest(t *testing.T, testCase validationTestCase) { httpRecorder := httptest.NewRecorder() m := martini.Classic() m.Post(testRoute, Validate(testCase.data), func(actual Errors) { expString := fmt.Sprintf("%+v", testCase.expectedErrors) actString := fmt.Sprintf("%+v", actual) if actString != expString { t.Errorf("For '%s': expected errors to be\n'%s'\nbut got\n'%s'", testCase.description, expString, actString) } }) req, err := http.NewRequest("POST", testRoute, nil) if err != nil { panic(err) } m.ServeHTTP(httpRecorder, req) switch httpRecorder.Code { case http.StatusNotFound: panic("Routing is messed up in test fixture (got 404): check methods and paths") case http.StatusInternalServerError: panic("Something bad happened on '" + testCase.description + "'") } }
func performFileTest(t *testing.T, binder handlerFunc, testCase fileTestCase) { httpRecorder := httptest.NewRecorder() m := martini.Classic() fileTestHandler := func(actual BlogPost, errs Errors) { assertFileAsExpected(t, testCase, actual.HeaderImage, testCase.singleFile) if len(testCase.multipleFiles) != len(actual.Pictures) { t.Errorf("For '%s': Expected %d multiple files, but actually had %d instead", testCase.description, len(testCase.multipleFiles), len(actual.Pictures)) } for i, expectedFile := range testCase.multipleFiles { if i >= len(actual.Pictures) { break } assertFileAsExpected(t, testCase, actual.Pictures[i], expectedFile) } } m.Post(testRoute, binder(BlogPost{}), func(actual BlogPost, errs Errors) { fileTestHandler(actual, errs) }) m.ServeHTTP(httpRecorder, buildRequestWithFile(testCase)) switch httpRecorder.Code { case http.StatusNotFound: panic("Routing is messed up in test fixture (got 404): check methods and paths") case http.StatusInternalServerError: panic("Something bad happened on '" + testCase.description + "'") } }
func performMultipartFormTest(t *testing.T, binder handlerFunc, testCase multipartFormTestCase) { httpRecorder := httptest.NewRecorder() m := martini.Classic() m.Post(testRoute, binder(BlogPost{}), func(actual BlogPost, errs Errors) { if testCase.shouldSucceed && len(errs) > 0 { t.Errorf("'%s' should have succeeded, but there were errors (%d):\n%+v", testCase.description, len(errs), errs) } else if !testCase.shouldSucceed && len(errs) == 0 { t.Errorf("'%s' should not have succeeded, but it did (there were no errors)", testCase.description) } expString := fmt.Sprintf("%+v", testCase.inputAndExpected) actString := fmt.Sprintf("%+v", actual) if actString != expString { t.Errorf("'%s': expected\n'%s'\nbut got\n'%s'", testCase.description, expString, actString) } }) multipartPayload, mpWriter := makeMultipartPayload(testCase) req, err := http.NewRequest("POST", testRoute, multipartPayload) if err != nil { panic(err) } req.Header.Add("Content-Type", mpWriter.FormDataContentType()) err = mpWriter.Close() if err != nil { panic(err) } if testCase.callFormValueBefore { req.FormValue("foo") } m.ServeHTTP(httpRecorder, req) switch httpRecorder.Code { case http.StatusNotFound: panic("Routing is messed up in test fixture (got 404): check methods and paths") case http.StatusInternalServerError: panic("Something bad happened on '" + testCase.description + "'") } }
// When binding from Form data, testing the type of data to bind // and converting a string into that type is tedious, so these tests // cover all those cases. func TestSetWithProperType(t *testing.T) { testInputs := map[string]string{ "successful": `integer=-1&integer8=-8&integer16=-16&integer32=-32&integer64=-64&uinteger=1&uinteger8=8&uinteger16=16&uinteger32=32&uinteger64=64&boolean_1=true&fl32_1=32.3232&fl64_1=-64.6464646464&str=string`, "errorful": `integer=&integer8=asdf&integer16=--&integer32=&integer64=dsf&uinteger=&uinteger8=asdf&uinteger16=+&uinteger32= 32 &uinteger64=+%20+&boolean_1=&boolean_2=asdf&fl32_1=asdf&fl32_2=&fl64_1=&fl64_2=asdfstr`, } expectedOutputs := map[string]Everything{ "successful": Everything{ Integer: -1, Integer8: -8, Integer16: -16, Integer32: -32, Integer64: -64, Uinteger: 1, Uinteger8: 8, Uinteger16: 16, Uinteger32: 32, Uinteger64: 64, Boolean_1: true, Fl32_1: 32.3232, Fl64_1: -64.6464646464, Str: "string", }, "errorful": Everything{}, } for key, testCase := range testInputs { httpRecorder := httptest.NewRecorder() m := martini.Classic() m.Post(testRoute, Form(Everything{}), func(actual Everything, errs Errors) { actualStr := fmt.Sprintf("%+v", actual) expectedStr := fmt.Sprintf("%+v", expectedOutputs[key]) if actualStr != expectedStr { t.Errorf("For '%s' expected\n%s but got\n%s", key, expectedStr, actualStr) } }) req, err := http.NewRequest("POST", testRoute, strings.NewReader(testCase)) if err != nil { panic(err) } req.Header.Set("Content-Type", formContentType) m.ServeHTTP(httpRecorder, req) } }
func performJsonTest(t *testing.T, binder handlerFunc, testCase jsonTestCase) { var payload io.Reader httpRecorder := httptest.NewRecorder() m := martini.Classic() jsonTestHandler := func(actual interface{}, errs Errors) { if testCase.shouldSucceedOnJson && len(errs) > 0 { t.Errorf("'%s' should have succeeded, but there were errors (%d):\n%+v", testCase.description, len(errs), errs) } else if !testCase.shouldSucceedOnJson && len(errs) == 0 { t.Errorf("'%s' should NOT have succeeded, but there were NO errors", testCase.description) } expString := fmt.Sprintf("%+v", testCase.expected) actString := fmt.Sprintf("%+v", actual) if actString != expString { t.Errorf("'%s': expected\n'%s'\nbut got\n'%s'", testCase.description, expString, actString) } } switch testCase.expected.(type) { case []Post: if testCase.withInterface { m.Post(testRoute, binder([]Post{}, (*modeler)(nil)), func(actual []Post, iface modeler, errs Errors) { for _, a := range actual { if a.Title != iface.Model() { t.Errorf("For '%s': expected the struct to be mapped to the context as an interface", testCase.description) } jsonTestHandler(a, errs) } }) } else { m.Post(testRoute, binder([]Post{}), func(actual []Post, errs Errors) { jsonTestHandler(actual, errs) }) } case Post: if testCase.withInterface { m.Post(testRoute, binder(Post{}, (*modeler)(nil)), func(actual Post, iface modeler, errs Errors) { if actual.Title != iface.Model() { t.Errorf("For '%s': expected the struct to be mapped to the context as an interface", testCase.description) } jsonTestHandler(actual, errs) }) } else { m.Post(testRoute, binder(Post{}), func(actual Post, errs Errors) { jsonTestHandler(actual, errs) }) } case BlogPost: if testCase.withInterface { m.Post(testRoute, binder(BlogPost{}, (*modeler)(nil)), func(actual BlogPost, iface modeler, errs Errors) { if actual.Title != iface.Model() { t.Errorf("For '%s': expected the struct to be mapped to the context as an interface", testCase.description) } jsonTestHandler(actual, errs) }) } else { m.Post(testRoute, binder(BlogPost{}), func(actual BlogPost, errs Errors) { jsonTestHandler(actual, errs) }) } } if testCase.payload == "-nil-" { payload = nil } else { payload = strings.NewReader(testCase.payload) } req, err := http.NewRequest("POST", testRoute, payload) if err != nil { panic(err) } req.Header.Set("Content-Type", testCase.contentType) m.ServeHTTP(httpRecorder, req) switch httpRecorder.Code { case http.StatusNotFound: panic("Routing is messed up in test fixture (got 404): check method and path") case http.StatusInternalServerError: panic("Something bad happened on '" + testCase.description + "'") default: if testCase.shouldSucceedOnJson && httpRecorder.Code != http.StatusOK && !testCase.shouldFailOnBind { t.Errorf("'%s' should have succeeded (except when using Bind, where it should fail), but returned HTTP status %d with body '%s'", testCase.description, httpRecorder.Code, httpRecorder.Body.String()) } } }
func performFormTest(t *testing.T, binder handlerFunc, testCase formTestCase) { httpRecorder := httptest.NewRecorder() m := martini.Classic() formTestHandler := func(actual interface{}, errs Errors) { if testCase.shouldSucceed && len(errs) > 0 { t.Errorf("'%s' should have succeeded, but there were errors (%d):\n%+v", testCase.description, len(errs), errs) } else if !testCase.shouldSucceed && len(errs) == 0 { t.Errorf("'%s' should have had errors, but there were none", testCase.description) } expString := fmt.Sprintf("%+v", testCase.expected) actString := fmt.Sprintf("%+v", actual) if actString != expString && !(testCase.deepEqual && reflect.DeepEqual(testCase.expected, actual)) { t.Errorf("'%s': expected\n'%s'\nbut got\n'%s'", testCase.description, expString, actString) } } switch testCase.expected.(type) { case Post: if testCase.withInterface { m.Post(testRoute, binder(Post{}, (*modeler)(nil)), func(actual Post, iface modeler, errs Errors) { if actual.Title != iface.Model() { t.Errorf("For '%s': expected the struct to be mapped to the context as an interface", testCase.description) } formTestHandler(actual, errs) }) } else { m.Post(testRoute, binder(Post{}), func(actual Post, errs Errors) { formTestHandler(actual, errs) }) m.Get(testRoute, binder(Post{}), func(actual Post, errs Errors) { formTestHandler(actual, errs) }) } case BlogPost: if testCase.withInterface { m.Post(testRoute, binder(BlogPost{}, (*modeler)(nil)), func(actual BlogPost, iface modeler, errs Errors) { if actual.Title != iface.Model() { t.Errorf("For '%s': expected the struct to be mapped to the context as an interface", testCase.description) } formTestHandler(actual, errs) }) } else { m.Post(testRoute, binder(BlogPost{}), func(actual BlogPost, errs Errors) { formTestHandler(actual, errs) }) } case EmbedPerson: m.Post(testRoute, binder(EmbedPerson{}), func(actual EmbedPerson, errs Errors) { formTestHandler(actual, errs) }) m.Get(testRoute, binder(EmbedPerson{}), func(actual EmbedPerson, errs Errors) { formTestHandler(actual, errs) }) } if testCase.method == "" { testCase.method = "POST" } req, err := http.NewRequest(testCase.method, testRoute+testCase.queryString, strings.NewReader(testCase.payload)) if err != nil { panic(err) } req.Header.Set("Content-Type", testCase.contentType) m.ServeHTTP(httpRecorder, req) switch httpRecorder.Code { case http.StatusNotFound: panic("Routing is messed up in test fixture (got 404): check methods and paths") case http.StatusInternalServerError: panic("Something bad happened on '" + testCase.description + "'") } }