Golang如何测试文件上传与下载_Golang 文件上传下载测试方法

首先编写文件上传处理函数并使用multipart/form-data模拟请求,通过httptest创建测试服务器,验证服务端能否正确解析并保存文件,再检查响应状态码和返回内容确保功能正常。

在Go语言开发中,测试文件上传与下载功能是构建Web服务时常见的需求。为了确保接口的可靠性,需要对这些功能进行充分的单元测试和集成测试。下面介绍如何使用标准库和常见模式来测试文件上传与下载。

1. 测试文件上传

文件上传通常通过HTTP的multipart/form-data格式实现。测试的关键是模拟客户端发送一个包含文件的请求,并验证服务端能否正确解析并保存文件。

示例:编写文件上传处理函数

func handleUpload(w http.ResponseWriter, r *http.Request) {
    err := r.ParseMultipartForm(32 << 20) // 32MB limit
    if err != nil {
        http.Error(w, "Unable to parse form", http.StatusBadRequest)
        return
    }

    file, handler, err := r.FormFile("uploadfile")
    if err != nil {
        http.Error(w, "Error retrieving file", http.StatusBadRequest)
        return
    }
    defer file.Close()

    // 模拟保存文件(实际可写入磁盘或存储系统)
    fmt.Fprintf(w, "Uploaded file: %s, Size: %d", handler.Filename, handler.Size)
}

测试代码:模拟上传请求

func TestUploadFile(t *testing.T) {
    body := new(bytes.Buffer)
    writer := multipart.NewWriter(body)
    part, _ := writer.CreateFormFile("uploadfile", "test.txt")
    part.Write([]byte("hello world"))
    writer.Close()

    req := httptest.NewRequest("POST", "/upload", body)
    req.Header.Set("Content-Type", writer.FormDataContentType())
    w := httptest.NewRecorder()

    handleUpload(w, req)

    if w.Code != http.StatusOK {
        t.Errorf("Expected status 200, got %d", w.Code)
    }

    expected := "Uploaded file: test.txt, Size: 11"
    if !strings.Contains(w.Body.String(), expected) {
        t.Errorf("Expected response to contain %q, got %q", expected, w.Body.String())
    }
}

2. 测试文件下载

文件下载接口通常返回文件内容,并设置适当的响应头(如Content-Disposition)。测试重点是验证响应头是否正确、文件内容是否匹配。

示例:文件下载处理函数

func handleDownload(w http.ResponseWriter, r *http.Request) {
    filename := r.URL.Query().Get("f")
    if filename == "" {
        http.Error(w, "Missing file name", http.StatusBadRequest)
        return
    }

    w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
    w.Header().Set("Content-Type", "application/octet-stream")

    fmt.Fprint(w, "mock file content")
}

测试代码:验证下载响应

func TestDownloadFile(t *testing.T) {
    req := httptest.NewRequest("GET", "/download?f=test.txt", nil)
    w := httptest.NewRecorder()

    handleDownload(w, req)

    if w.Code != http.StatusOK {
        t.Errorf("Expected 200 OK, got %v", w.Code)
    }

    content := w.Header().Get("Content-Type")
    if content != "application/octet-stream" {
        t.Errorf("Expected Content-Type application/octet-stream, got %s", content)
    }

    disposition := w.Header().Get("Content-Disposition")
    if !strings.Contains(disposition, "attachment; filename=test.txt") {
        t.Errorf("Wrong Content-Disposition: %s", disposition)
    }

    body := w.Body.String()
    if body != "mock file content" {
        t.Errorf("Expected body 'mock file content', got %q", body)
    }
}

3. 使用httptest进行集成测试

将上传和下载接口注册到路由中,可以通过net/http/httptest启动一个临时服务器进行端到端测试。

func TestIntegration(t *testing.T) {
    mux := http.NewServeMux()
    mux.HandleFunc("/upload", handleUpload)
    mux.HandleFunc("/download", handleDownload)

    server := httptest.NewServer(mux)
    defer server.Close()

    // 测试上传
    resp, err := http.Post(server.URL+"/upload", "text/plain", strings.NewReader("test data"))
    if err != nil {
        t.Fatal(err)
    }
    resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        t.Errorf("Upload failed with status: %d", resp.StatusCode)
    }
}

基本上就这些。通过构造模拟请求、使用httptestmultipart工具,可以完整覆盖文件上传下载的核心逻辑。测试时注意边界情况,比如空文件、大文件、缺失参数等,能有效提升接口健壮性。