我在Golang中编写了以下代码:
func Test_HandlerError_EdpointsReturnError(t *testing.T) {
assert := assert.New(t)
objExpected := BodyForTest{ID: 2}
endpointInternalErr := func(w http.ResponseWriter, r *http.Request) (interface{}, int, error) {
return nil, 0, internalerrors.ErrInternal
}
endpointDomainErr := func(w http.ResponseWriter, r *http.Request) (interface{}, int, error) {
return nil, 0, errors.New("Domain Error")
}
endpointObjAndStatus := func(w http.ResponseWriter, r *http.Request) (interface{}, int, error) {
return objExpected, 201, nil
}
handlerFuncToInternalErr := HandlerError(endpointInternalErr)
handlerFuncToDomainErr := HandlerError(endpointDomainErr)
handlerFuncToObjAndStatus := HandlerError(endpointObjAndStatus)
req, _ := http.NewRequest("GET", "/", nil)
res := httptest.NewRecorder()
handlerFuncToInternalErr.ServeHTTP(res, req)
handlerFuncToDomainErr.ServeHTTP(res, req)
handlerFuncToObjAndStatus.ServeHTTP(res, req)
if http.StatusInternalServerError == res.Code {
// INTERNAL ERROR
assert.Equal(http.StatusInternalServerError, res.Code)
assert.Contains(res.Body.String(), internalerrors.ErrInternal.Error())
}
if http.StatusBadRequest == res.Code {
// DOMAIN ERROR
assert.Equal(http.StatusBadRequest, res.Code)
assert.Contains(res.Body.String(), "Domain Error")
}
if http.StatusCreated == res.Code {
assert.Equal(http.StatusCreated, res.Code)
objReturned := BodyForTest{}
json.Unmarshal(res.Body.Bytes(), &objReturned)
assert.Equal(objExpected, objReturned)
}
}
最后你可以看到,有很多
Ifs
,只是为了进行测试,每个 if 都是为了测试不同的东西。问题是,我从一位编写了类似代码的老师那里得到了这个,唯一的区别是,他没有像我那样将所有代码都放在 Ifs
的同一个 func 上,而是为每个测试执行一个 func。
当我写它时,我期望它能起作用,因为不知怎的,只在一个函数上测试它是有意义的,而且它确实起作用了!但后来我又读了一遍,注意到在我的 Ifs
上,我正在比较不同类型的 http 状态与相同的 var res
,所以这就是让我着迷的原因,为什么当他们都在比较时他们都表现得很好本身为同一个变量?
另外,另一个疑问是,如果我正在做的事情可以被认为是一种不好的编码实践,因为我不是为每种类型的测试使用多个函数,而是只在一个函数上测试它,我还在检查
if
上的要求是否匹配,所以我可以使用 assert
包中的 func testify
来测试它,但它总是没问题,因为如果 if
为 true ,那么 assert.Equal
函数就可以工作了。这是错误的吗?
首先,我的代码是用
if
和 else ifs
编写的,但我注意到,除了它可以工作之外,并不理想,因为测试显然在第一次匹配时停止,所以它不会甚至转到其他人,所以然后我将其全部更改为多个Ifs
,但就在那时我注意到它可能会出错,考虑到我正在将不同的条目与一个变量进行比较。但不知怎的,它正在发挥作用。但为什么?不是应该不行吗?
测试中 if 条件的存在意味着您不了解测试中发生的情况并允许不同的场景。测试应该是线性的且明确的。使测试明确的最佳方法是使用表驱动测试(https://dave.cheney.net/2019/05/07/prefer-table-driven-tests),或者将一个测试分成多个测试通过 t.Run 进行子测试(顺便说一句,这在表驱动测试中看起来也很棒)。
您的代码不起作用,所以这是一个不起作用的示例解决方案:
func Test_HandlerError_EdpointsReturnError(t *testing.T) {
t.Run(`internal`, func(t *testing.T) {
handler := func(w http.ResponseWriter, r *http.Request) (interface{}, int, error) {
return nil, 0, internalerrors.ErrInternal
}
handler.ServeHTTP(res, req)
req, err := http.NewRequest("GET", "/", nil)
require.NoError(t, err)
res := httptest.NewRecorder()
assert.Equal(t, http.StatusInternalServerError, res.Code)
assert.Contains(t, res.Body.String(), internalerrors.ErrInternal.Error())
})
t.Run(`domain`, func(t *testing.T) {
})
t.Run(`success`, func(t *testing.T) {
})
}