Golang测试文件上传功能的方法与实践

Golang测试文件上传功能的方法与实践 大家好 请告诉我如何为我的简单文件上传处理程序正确编写测试

func UploadFile(w http.ResponseWriter, r *http.Request) {
    r.ParseMultipartForm(1024)
	file, _, err := r.FormFile("uploadFile")
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		io.WriteString(w, "Invalid file to upload")
		return
	}
	defer file.Close()

	fileBytes, err := ioutil.ReadAll(file)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		io.WriteString(w, "Read file error - Invalid data in file")
		return
	}
}

我想从包内的tmp文件夹获取测试文件,并在测试中使用此文件发送请求 谢谢!


更多关于Golang测试文件上传功能的方法与实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

到目前为止你写了什么?我不认为你的提问方式正确:首先你应该告诉我们你尝试了什么,然后我们才会告诉你接下来该尝试什么。我们不是来这里为你写代码的。

举个例子,你可以实现自己的(模拟)http.ResponseWriter 来测试是否获取到了正确的数据。这样你就不需要写入磁盘,而单元测试通常也不应该做这种事情。

更多关于Golang测试文件上传功能的方法与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


以下是针对文件上传处理程序的测试实现,使用Go标准库的httptest包和测试文件:

package main

import (
    "bytes"
    "io"
    "mime/multipart"
    "net/http"
    "net/http/httptest"
    "os"
    "path/filepath"
    "testing"
)

func TestUploadFile(t *testing.T) {
    // 创建测试文件
    tmpDir := "tmp"
    testFileName := "testfile.txt"
    testFilePath := filepath.Join(tmpDir, testFileName)
    
    // 确保tmp目录存在
    if err := os.MkdirAll(tmpDir, 0755); err != nil {
        t.Fatalf("Failed to create tmp directory: %v", err)
    }
    
    // 创建测试文件内容
    testContent := "This is a test file content"
    if err := os.WriteFile(testFilePath, []byte(testContent), 0644); err != nil {
        t.Fatalf("Failed to create test file: %v", err)
    }
    defer os.RemoveAll(tmpDir)

    // 打开测试文件
    file, err := os.Open(testFilePath)
    if err != nil {
        t.Fatalf("Failed to open test file: %v", err)
    }
    defer file.Close()

    // 创建multipart表单
    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)
    part, err := writer.CreateFormFile("uploadFile", testFileName)
    if err != nil {
        t.Fatalf("Failed to create form file: %v", err)
    }
    
    // 复制文件内容到表单
    _, err = io.Copy(part, file)
    if err != nil {
        t.Fatalf("Failed to copy file content: %v", err)
    }
    writer.Close()

    // 创建测试请求
    req := httptest.NewRequest("POST", "/upload", body)
    req.Header.Set("Content-Type", writer.FormDataContentType())
    
    // 创建响应记录器
    rr := httptest.NewRecorder()
    
    // 调用处理函数
    UploadFile(rr, req)

    // 检查响应状态码
    if status := rr.Code; status != http.StatusOK {
        t.Errorf("Handler returned wrong status code: got %v want %v", status, http.StatusOK)
    }
}

func TestUploadFile_InvalidFile(t *testing.T) {
    // 测试无效文件上传
    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)
    // 不添加任何文件字段
    writer.Close()

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

    // 应该返回400状态码
    if status := rr.Code; status != http.StatusBadRequest {
        t.Errorf("Handler returned wrong status code: got %v want %v", status, http.StatusBadRequest)
    }
    
    expected := "Invalid file to upload"
    if rr.Body.String() != expected {
        t.Errorf("Handler returned unexpected body: got %v want %v", rr.Body.String(), expected)
    }
}

func TestUploadFile_ReadError(t *testing.T) {
    // 模拟读取错误的情况
    tmpDir := "tmp"
    testFileName := "testfile.txt"
    testFilePath := filepath.Join(tmpDir, testFileName)
    
    os.MkdirAll(tmpDir, 0755)
    // 创建空文件
    os.WriteFile(testFilePath, []byte{}, 0644)
    defer os.RemoveAll(tmpDir)

    file, _ := os.Open(testFilePath)
    defer file.Close()

    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)
    part, _ := writer.CreateFormFile("uploadFile", testFileName)
    
    // 这里可以模拟读取错误,但实际测试中文件为空应该能正常处理
    io.Copy(part, file)
    writer.Close()

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

    // 检查响应
    if rr.Code != http.StatusBadRequest {
        t.Errorf("Expected status %v, got %v", http.StatusBadRequest, rr.Code)
    }
}

注意:你的原始处理函数需要返回成功状态码才能通过测试。建议在处理成功时添加:

// 在处理函数成功时添加
w.WriteHeader(http.StatusOK)
io.WriteString(w, "File uploaded successfully")

测试文件结构:

project/
├── main.go
├── tmp/
│   └── testfile.txt
└── main_test.go

运行测试:

go test -v
回到顶部