Golang的http处理程序测试的模拟函数

huangapple go评论93阅读模式
英文:

Golang mocking functions for http handler tests

问题

我正在为我的PostLoginHandler编写单元测试,并需要模拟一个会话中间件函数。在我的处理程序中,它调用session.Update(),我希望模拟返回nil。

在阅读了各种答案后,我首先的直觉是创建一个SessionManager接口,但即使如此,我仍然不清楚如何继续。

main.go:

func PostLoginHandler(c web.C, w http.ResponseWriter, r *http.Request) {
    r.ParseForm()
    user, pass := r.PostFormValue("username"), r.PostFormValue("password")
    ctx := context.GetContext(c)

    if !authorizeUser(user, pass) {
        http.Error(w, "Wrong username or password", http.StatusBadRequest)
        return
    }

    ctx.IsLogin = true
    err := session.Update(ctx) // 模拟这个函数调用。
    if err != nil {
        log.Println(err)
        return
    }
    http.Redirect(w, r, "/admin/", http.StatusFound)
}

main_test:

var loginTests = []struct {
    username string
    password string
    code     int
}{
    {"admin", "admin", http.StatusFound},
    {"", "", http.StatusBadRequest},
    {"", "admin", http.StatusBadRequest},
    {"admin", "", http.StatusBadRequest},
    {"admin", "badpassword", http.StatusBadRequest},
}

func TestPostLoginHandler(t *testing.T) {
    // setup()
    ctx := &context.Context{IsLogin: false, Data: make(map[string]interface{})}
    c := newC()
    c.Env["context"] = ctx

    for k, test := range loginTests {
        v := url.Values{}
        v.Set("username", test.username)
        v.Set("password", test.password)
        r, _ := http.NewRequest("POST", "/login", nil)
        r.PostForm = v
        resp := httptest.NewRecorder()
        m.ServeHTTPC(c, resp, r)

        if resp.Code != test.code {
            t.Fatalf("TestPostLoginHandler #%v failed. Expected: %v\tReceived: %v", k, test.code, resp.Code)
        }
    }
}
英文:

I am writing a unit test for my PostLoginHandler and need to mock a session middleware function. In my handler it calls session.Update() that I would like to mock to return nil.

My first instinct after reading various answers was to make a SessionManager interface but even then I am unclear how to proceed.

main.go:

func PostLoginHandler(c web.C, w http.ResponseWriter, r *http.Request) {
	r.ParseForm()
	user, pass := r.PostFormValue("username"), r.PostFormValue("password")
	ctx := context.GetContext(c)

	if !authorizeUser(user, pass) {
		http.Error(w, "Wrong username or password", http.StatusBadRequest)
		return
	}

	ctx.IsLogin = true
	err := session.Update(ctx) \\ mock this function call.
	if err != nil {
		log.Println(err)
		return
	}
	http.Redirect(w, r, "/admin/", http.StatusFound)
}

main_test:

var loginTests = []struct {
	username string
	password string
	code     int
}{
	{"admin", "admin", http.StatusFound},
	{"", "", http.StatusBadRequest},
	{"", "admin", http.StatusBadRequest},
	{"admin", "", http.StatusBadRequest},
	{"admin", "badpassword", http.StatusBadRequest},
}

func TestPostLoginHandler(t *testing.T) {
	//	setup()
	ctx := &context.Context{IsLogin: false, Data: make(map[string]interface{})}
	c := newC()
	c.Env["context"] = ctx

	for k, test := range loginTests {
		v := url.Values{}
		v.Set("username", test.username)
		v.Set("password", test.password)
		r, _ := http.NewRequest("POST", "/login", nil)
		r.PostForm = v
		resp := httptest.NewRecorder()
		m.ServeHTTPC(c, resp, r)

		if resp.Code != test.code {
			t.Fatalf("TestPostLoginHandler #%v failed. Expected: %v\tReceived: %v", k, test.code, resp.Code)
		}
	}
}

答案1

得分: 4

我为你推荐一对链接:

Testing in Go - Github: 这个链接解释了如何使用mux包来进行模拟路由和响应。

示例:

func TestUsersService_Get_specifiedUser(t *testing.T) {
    setup()
    defer teardown()

    mux.HandleFunc("/users/u", 
        func(w http.ResponseWriter, r *http.Request) {
            testMethod(t, r, "GET")
            fmt.Fprint(w, `{"id":1}`)
        }
    )

    user, _, err := client.Users.Get("u")
    if err != nil {
        t.Errorf("Users.Get返回错误:%v", err)
    }

    want := &User{ID: Int(1)}
    if !reflect.DeepEqual(user, want) {
       t.Errorf("Users.Get返回了%+v,期望是%+v", 
                user, want)
    }
}  

testflight: 这是一个用于向服务器发送简单HTTP请求的包,使用testflight和mux进行模拟端点,可以进行完美的测试。

示例:

func TestPostWithForm(t *testing.T) {
    testflight.WithServer(Handler(), func(r *testflight.Requester) {
        response := r.Post("/post/form", testflight.FORM_ENCODED, "name=Drew")

        assert.Equal(t, 201, response.StatusCode)
        assert.Equal(t, "Drew created", response.Body)
    })
}
英文:

I recommend you a pair of links:

Testing in Go - Github: This link explain how do a mock route with a response using mux package.

Example:

func TestUsersService_Get_specifiedUser(t *testing.T) {
    setup()
    defer teardown()

    mux.HandleFunc("/users/u", 
        func(w http.ResponseWriter, r *http.Request) {
            testMethod(t, r, "GET")
            fmt.Fprint(w, `{"id":1}`)
        }
    )

    user, _, err := client.Users.Get("u")
    if err != nil {
        t.Errorf("Users.Get returned error: %v", err)
    }

    want := &User{ID: Int(1)}
    if !reflect.DeepEqual(user, want) {
       t.Errorf("Users.Get returned %+v, want %+v", 
                user, want)
    }
}  

testflight: A package for make simple http request to a server, using testflight and mux for make mock endpoints you will can do a perfect test.

Example:

func TestPostWithForm(t *testing.T) {
    testflight.WithServer(Handler(), func(r *testflight.Requester) {
        response := r.Post("/post/form", testflight.FORM_ENCODED, "name=Drew")

        assert.Equal(t, 201, response.StatusCode)
        assert.Equal(t, "Drew created", response.Body)
    })
}

huangapple
  • 本文由 发表于 2015年3月6日 03:07:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/28885705.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定