golang RESTful API集成测试微框架插件restit的使用
golang RESTful API集成测试微框架插件restit的使用
RESTit 是一个Go微框架,用于帮助编写RESTful API的集成测试。它主要针对基于JSON的RESTful API提供测试辅助工具。
框架简介
RESTit旨在使集成测试具备以下特点:
- 可读性强
- 高度可重用
- 易于修改
版本信息
RESTit库的不同版本位于不同目录下:
- 稳定版本 (版本1):API稳定,仅接收bug修复
- 开发版本 (版本2):正在积极开发中,可能会有新功能(可能导致API变更)
示例代码
下面是一个使用RESTit进行API测试的完整示例:
package main
import (
"testing"
"github.com/go-restit/restit/v1"
)
// 定义测试数据结构
type Post struct {
ID int `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
}
func TestGetPost(t *testing.T) {
// 创建测试客户端
client := restit.New("https://jsonplaceholder.typicode.com")
// 定义期望的响应结构
var post Post
// 执行GET请求并验证响应
client.Get("/posts/1").
Expect(t).
Status(200). // 期望状态码200
Header("Content-Type", "application/json"). // 期望响应头
JSON(&post). // 解析JSON响应
Run()
// 验证响应数据
if post.ID != 1 {
t.Errorf("expected post ID to be 1, got %d", post.ID)
}
}
func TestCreatePost(t *testing.T) {
// 创建测试客户端
client := restit.New("https://jsonplaceholder.typicode.com")
// 准备请求数据
newPost := Post{
Title: "Test Post",
Body: "This is a test post",
}
// 定义期望的响应结构
var createdPost Post
// 执行POST请求并验证响应
client.Post("/posts").
JSON(newPost). // 设置请求体
Expect(t).
Status(201). // 期望状态码201
JSON(&createdPost). // 解析JSON响应
Run()
// 验证响应数据
if createdPost.Title != newPost.Title {
t.Errorf("expected title to be %q, got %q", newPost.Title, createdPost.Title)
}
}
主要功能
- 请求构建:支持GET、POST、PUT、DELETE等HTTP方法
- 响应验证:可以验证状态码、响应头和响应体
- JSON处理:自动序列化和反序列化JSON数据
- 测试断言:内置丰富的断言方法
错误报告
如果发现问题,可以通过项目的issue tracker提交错误报告。同时欢迎提交补丁和pull请求。
这个示例展示了如何使用RESTit进行基本的API测试,包括GET和POST请求的发送与验证。你可以根据实际需求扩展这个基础示例。
更多关于golang RESTful API集成测试微框架插件restit的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang RESTful API集成测试微框架插件restit的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用restit进行Golang RESTful API集成测试
restit是一个轻量级的Golang RESTful API集成测试框架,它提供了简洁的API来测试HTTP服务。下面我将介绍如何使用restit进行API测试。
安装restit
首先安装restit包:
go get github.com/yookoala/restit
基本用法
1. 简单GET请求测试
package main
import (
"fmt"
"github.com/yookoala/restit"
"net/http"
"net/http/httptest"
"testing"
)
func TestGetRequest(t *testing.T) {
// 创建一个测试服务器
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, `{"status": "ok", "message": "success"}`)
}))
defer ts.Close()
// 使用restit发送GET请求
resp, err := restit.Get(restit.URL(ts.URL))
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
// 验证响应状态码
if resp.StatusCode() != http.StatusOK {
t.Errorf("Expected status 200, got %d", resp.StatusCode())
}
// 验证JSON响应内容
expected := `{"status": "ok", "message": "success"}`
if resp.String() != expected+"\n" {
t.Errorf("Expected response %q, got %q", expected, resp.String())
}
}
2. POST请求测试
func TestPostRequest(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 验证请求体
body := make([]byte, r.ContentLength)
r.Body.Read(body)
if string(body) != `{"name":"test"}` {
w.WriteHeader(http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusCreated)
fmt.Fprintln(w, `{"id": 123}`)
}))
defer ts.Close()
// 发送POST请求
resp, err := restit.Post(
restit.URL(ts.URL),
restit.ContentType("application/json"),
restit.Body(`{"name":"test"}`),
)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
// 验证响应状态码
if resp.StatusCode() != http.StatusCreated {
t.Errorf("Expected status 201, got %d", resp.StatusCode())
}
// 解析JSON响应
var result struct {
ID int `json:"id"`
}
if err := resp.JSON(&result); err != nil {
t.Errorf("Failed to parse JSON: %v", err)
}
if result.ID != 123 {
t.Errorf("Expected ID 123, got %d", result.ID)
}
}
3. 更复杂的测试场景
func TestAuthAPI(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 验证授权头
if r.Header.Get("Authorization") != "Bearer test-token" {
w.WriteHeader(http.StatusUnauthorized)
return
}
// 根据路径返回不同响应
switch r.URL.Path {
case "/user":
fmt.Fprintln(w, `{"name": "John", "age": 30}`)
case "/items":
fmt.Fprintln(w, `[{"id":1,"name":"item1"},{"id":2,"name":"item2"}]`)
default:
w.WriteHeader(http.StatusNotFound)
}
}))
defer ts.Close()
// 测试带认证头的请求
t.Run("TestAuthenticatedRequest", func(t *testing.T) {
resp, err := restit.Get(
restit.URL(ts.URL+"/user"),
restit.AddHeader("Authorization", "Bearer test-token"),
)
if err != nil {
t.Fatal(err)
}
if resp.StatusCode() != http.StatusOK {
t.Errorf("Expected status 200, got %d", resp.StatusCode())
}
var user struct {
Name string `json:"name"`
Age int `json:"age"`
}
if err := resp.JSON(&user); err != nil {
t.Fatal(err)
}
if user.Name != "John" || user.Age != 30 {
t.Errorf("Unexpected user data: %+v", user)
}
})
// 测试未授权请求
t.Run("TestUnauthorizedRequest", func(t *testing.T) {
resp, err := restit.Get(restit.URL(ts.URL+"/user"))
if err != nil {
t.Fatal(err)
}
if resp.StatusCode() != http.StatusUnauthorized {
t.Errorf("Expected status 401, got %d", resp.StatusCode())
}
})
}
高级特性
1. 使用Expect简化断言
func TestExpect(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, `{"status": "ok"}`)
}))
defer ts.Close()
resp, err := restit.Get(restit.URL(ts.URL))
if err != nil {
t.Fatal(err)
}
// 使用Expect进行断言
resp.
Expect(t). // 开始断言链
Status(http.StatusOK). // 验证状态码
Header("Content-Type", "application/json"). // 验证头部
JSON(map[string]interface{}{ // 验证JSON
"status": "ok",
})
}
2. 测试文件上传
func TestFileUpload(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
file, header, err := r.FormFile("file")
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
defer file.Close()
if header.Filename != "test.txt" {
w.WriteHeader(http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintln(w, `{"size": `+fmt.Sprint(header.Size)+`}`)
}))
defer ts.Close()
// 创建一个临时文件
tmpFile, err := os.CreateTemp("", "test-*.txt")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpFile.Name())
if _, err := tmpFile.WriteString("test content"); err != nil {
t.Fatal(err)
}
tmpFile.Close()
// 发送文件上传请求
resp, err := restit.Post(
restit.URL(ts.URL),
restit.File("file", tmpFile.Name()),
)
if err != nil {
t.Fatal(err)
}
resp.Expect(t).
Status(http.StatusOK).
JSON(map[string]interface{}{
"size": 12, // "test content"的长度
})
}
总结
restit提供了简洁的API来测试RESTful服务,主要特点包括:
- 支持各种HTTP方法(GET, POST, PUT, DELETE等)
- 方便设置请求头、内容类型和请求体
- 支持文件上传测试
- 提供Expect链式断言简化测试代码
- 支持JSON响应解析和验证
对于更复杂的测试场景,可以结合标准库的httptest和restit一起使用。restit特别适合在开发微服务时进行集成测试,保持测试代码简洁易读。