[英]What's the most idiomatic way of testing functions with HTTP requests in Go?
[英]What is the idiomatic way to test wrapper functions in Golang?
這並不罕見,當我們有一個帶有很多參數的 function 時,創建一些使用帶有預定義參數的通用 function 的伴隨函數。 這是定義參數默認值的通常替代方法,Go 不允許這樣做。
一個非常簡單的示例是創建一個SquareArea
function,它使用更通用的RectangleArea
function。
func SquareArea(side int) int {
return RectangleArea(side, side)
}
func RectangleArea(width int, length int) int {
if width < 0 || length < 0 {
return 0
}
return width * length
}
對於這些功能,可以創建(有點)表測試
func TestSquareArea(t *testing.T) {
tests := []struct {
side int
expected int
}{
{side: -1, expected: 0},
{side: 0, expected: 0},
{side: 1, expected: 1},
{side: 2, expected: 4},
{side: 100, expected: 10000},
}
for idx, test := range tests {
if result := SquareArea(test.side); test.expected != result {
t.Errorf("test #%d expected != result (%d!=%d)", idx, test.expected, result)
}
}
}
func TestRectangleArea(t *testing.T) {
tests := []struct {
width int
length int
expected int
}{
{width: -1, length: -1, expected: 0},
{width: -1, length: 1, expected: 0},
{width: 1, length: -1, expected: 0},
{width: 2, length: 1, expected: 2},
{width: 1, length: 2, expected: 2},
{width: 3, length: 2, expected: 6},
{width: 2, length: 3, expected: 6},
{width: 10, length: 100, expected: 1000},
{width: 100, length: 10, expected: 1000},
}
for idx, test := range tests {
if result := RectangleArea(test.width, test.length); test.expected != result {
t.Errorf("test #%d expected != result (%d!=%d)", idx, test.expected, result)
}
}
}
這是正確的方法嗎?
對於更復雜的功能和更多的配套功能,這種方法似乎會創建大量測試,同時實質上會多次測試相同的底層代碼(即RectangleArea
)。
我覺得測試SquareArea
應該只確保使用正確的參數調用RectangleArea
。
這種代碼方法(同時具有RectangleArea
和SquareArea
功能)在 Golang 中是慣用的嗎? 在 Golang 上還有其他方法嗎?
使用像 Python 這樣的語言,我會模擬RectangleArea
function。
為了模仿這一點,我會做類似的事情:
var rectangleAreaFunction = RectangleArea
func SquareArea(side int) int {
return rectangleAreaFunction(side, side)
}
func RectangleArea(width int, length int) int {
if width < 0 || length < 0 {
return 0
}
return width * length
}
通過測試:
func TestSquareArea(t *testing.T) {
call:= ""
mock:= func(width int, length int) int {
call = fmt.Sprintf("func(%d,%d)", width, length)
return 0
}
rectangleAreaFunction = mock
tests := []struct {
side int
expected string
}{
{side: -1, expected: "func(-1,-1)"},
{side: 0, expected: "func(0,0)"},
{side: 1, expected: "func(1,1)"},
{side: 2, expected: "func(2,2)"},
{side: 100, expected: "func(100,100)"},
}
for idx, test := range tests {
call = ""
SquareArea(test.side)
if test.expected != call {
t.Errorf("test #%d expected != call (%s!=%s)", idx, test.expected, call)
}
}
}
func TestRectangleArea(t *testing.T) {
tests := []struct {
width int
length int
expected int
}{
{width: -1, length: -1, expected: 0},
{width: -1, length: 1, expected: 0},
{width: 1, length: -1, expected: 0},
{width: 2, length: 1, expected: 2},
{width: 1, length: 2, expected: 2},
{width: 3, length: 2, expected: 6},
{width: 2, length: 3, expected: 6},
{width: 10, length: 100, expected: 1000},
{width: 100, length: 10, expected: 1000},
}
for idx, test := range tests {
if result := RectangleArea(test.width, test.length); test.expected != result {
t.Errorf("test #%d expected != result (%d!=%d)", idx, test.expected, result)
}
}
}
但是似乎使用變量來保存實際的 function 來進行測試是不好的。
這種情況的另一個例子是通過第一次分類 function 處理 http 請求方法時:
func Triage(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
// some other common code like adding some context
*r = *(r.WithContext(context.WithValue(r.Context(), "key", "value")))
switch r.Method {
case POST:
triagePost(w, r)
default:
triageGet(w, r)
}
}
func triagePost(w http.ResponseWriter, r *http.Request) {
// some code
}
func triageGet(w http.ResponseWriter, r *http.Request) {
// some code
}
對這 3 個功能的完整測試將有很多無用的重復將Triage
function 的測試限制為:
r.Method
正確調用了正確的 function( triagePost
或triageGet
)將在測試實際行為時防止此類重復。
或者在 Golang 中擁有這種類型的代碼(分類功能)是完全不正確的?
Go盡量避免mocking。 讓我們嘗試遵循慣用的方法(測試真實代碼),看看它能帶給我們多遠。
Function SquareArea 使用相同的兩個參數值調用 RectangleArea。 測試 SquareArea 並不關心 RectangleArea 的正確性。
SquareArea 的單個測試用例將提供 100% 的測試覆蓋率,甚至不需要表驅動測試。
如果擔心在給定兩個相同值的參數時測試 RectangleArea 的正確性,則應將此測試用例直接添加到 RectangleArea 的表驅動測試中。
當然,如果 SquareArea 更復雜,那么我們將需要一個表驅動測試。 但在這種情況下,我們也必須關注 SquareArea 的作用,而不是RectangleArea 的作用。
換句話說,在決定如何測試 function(或任何實際的東西)時,我發現以下方法有助於減少疑慮:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.