Repository: gin-gonic/gin
File: binding/binding_test.go (Go)

Code before:
	obj := FooStruct{}
	req := requestWithBody("POST", path, body)
	req.Header.Add("Content-Type", MIMEMSGPACK)
	err := b.Bind(req, &obj)
	assert.NoError(t, err)
	assert.Equal(t, "bar", obj.Foo)

	obj = FooStruct{}
	req = requestWithBody("POST", badPath, badBody)
	req.Header.Add("Content-Type", MIMEMSGPACK)
	err = MsgPack.Bind(req, &obj)
	assert.Error(t, err)
}

func requestWithBody(method, path, body string) (req *http.Request) {
	req, _ = http.NewRequest(method, path, bytes.NewBufferString(body))
	return
}

type bindTestData struct {
	need interface{}
	got  interface{}
	in   map[string][]string
}

func Test_Binding_BaseType(t *testing.T) {
	type needFixDurationEmpty struct {
		Duration time.Duration `form:"duration"`
	}

	type needFixUnixNanoEmpty struct {
		CreateTime time.Time `form:"createTime" time_format:"unixNano"`
	}

	tests := []bindTestData{
		{need: &needFixDurationEmpty{}, got: &needFixDurationEmpty{}, in: http.Header{"duration": []string{}}},
		{need: &needFixUnixNanoEmpty{}, got: &needFixUnixNanoEmpty{}, in: http.Header{"createTime": []string{}}},
	}

	for _, v := range tests {
		err := mapForm(v.got, v.in)
		assert.NoError(t, err)
		assert.Equal(t, v.need, v.got)
	}
}


Review comment (refactor):
Please split this method by 2 different test cases (2 different methods) and move them in `form_mapping_test.go` file:
1: set `time.Duration` (as example, you could extend the existed method `TestMapiingTimeDuration` in `form_mapping_test.go` file)
2: set `time.Time` with `unixNano` (as example, method `TestMappingTimeUnixNano`)

Code after:
func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
	assert.Equal(t, name, b.Name())

	obj := FooStructUseNumber{}
	req := requestWithBody(http.MethodPost, path, body)
	EnableDecoderUseNumber = true
	err := b.Bind(req, &obj)
	require.NoError(t, err)
	// we hope it is int64(123)
	v, e := obj.Foo.(json.Number).Int64()
	require.NoError(t, e)
	assert.Equal(t, int64(123), v)

	obj = FooStructUseNumber{}
	req = requestWithBody(http.MethodPost, badPath, badBody)
	err = JSON.Bind(req, &obj)
	require.Error(t, err)
}

func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, body, badBody string) {
	assert.Equal(t, name, b.Name())

	obj := FooStructUseNumber{}
	req := requestWithBody(http.MethodPost, path, body)
	EnableDecoderUseNumber = false
	err := b.Bind(req, &obj)
	require.NoError(t, err)
	// it will return float64(123) if not use EnableDecoderUseNumber
	// maybe it is not hoped
	assert.InDelta(t, float64(123), obj.Foo, 0.01)

	obj = FooStructUseNumber{}
	req = requestWithBody(http.MethodPost, badPath, badBody)
	err = JSON.Bind(req, &obj)
	require.Error(t, err)
}

func testBodyBindingDisallowUnknownFields(t *testing.T, b Binding, path, badPath, body, badBody string) {
	EnableDecoderDisallowUnknownFields = true
	defer func() {
		EnableDecoderDisallowUnknownFields = false
	}()

	obj := FooStructDisallowUnknownFields{}
	req := requestWithBody(http.MethodPost, path, body)
	err := b.Bind(req, &obj)
	require.NoError(t, err)
	assert.Equal(t, "bar", obj.Foo)

	obj = FooStructDisallowUnknownFields{}
	req = requestWithBody(http.MethodPost, badPath, badBody)