Skip to content

update: coverage #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ jobs:

- name: Build
run: go build -v ./...
- name: Test
run: go test -v -race ./...
- name: Benchmark
run: go test -race -run=^$ -bench=. -benchmem ./...
- name: Coverage
run: go test -coverprofile=coverage.txt
- name: Test
run: go test -v -race -coverprofile=coverage.txt ./...
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
Expand Down
2 changes: 1 addition & 1 deletion request.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func makeBody(body any) (io.Reader, error) {
return bytes.NewReader(v), nil
case string:
return strings.NewReader(v), nil
case *bytes.Buffer, bytes.Buffer:
case *bytes.Buffer:
return body.(io.Reader), nil
case io.Reader, io.ReadSeeker, *bytes.Reader, *strings.Reader:
return body.(io.Reader), nil
Expand Down
151 changes: 113 additions & 38 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,110 @@ package requests
import (
"bytes"
"context"
"io"
"net/http"
"net/url"
"strings"
"testing"
)

func Test_makeBody(t *testing.T) {
func TestMakeBody(t *testing.T) {
tests := []struct {
name string
body any
want string
wantErr bool
}{
{
name: "nil body",
body: nil,
want: "",
},
{
name: "byte slice body",
name: "byte slice",
body: []byte("test data"),
want: "test data",
},
{
name: "string body",
body: "test data",
name: "string",
body: "test string",
want: "test string",
},
{
name: "bytes buffer body",
body: bytes.NewBuffer([]byte("test data")),
name: "bytes.Buffer pointer",
body: bytes.NewBuffer([]byte("buffer data")),
want: "buffer data",
},
{
name: "io.Reader body",
body: strings.NewReader("test data"),
name: "strings.Reader",
body: strings.NewReader("reader data"),
want: "reader data",
},
{
name: "url.Values body",
name: "url.Values",
body: url.Values{"key": {"value"}},
want: "key=value",
},
{
name: "struct body",
name: "func returning ReadCloser",
body: func() (io.ReadCloser, error) {
return io.NopCloser(strings.NewReader("func data")), nil
},
want: "func data",
},
{
name: "struct to JSON",
body: struct {
Name string `json:"name"`
}{"test"},
Key string `json:"key"`
}{Key: "value"},
want: `{"key":"value"}`,
},
{
name: "error func",
body: func() (io.ReadCloser, error) {
return nil, io.EOF
},
wantErr: true,
},
{
name: "invalid JSON",
body: make(chan int),
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
reader, err := makeBody(tt.body)
if (err != nil) != tt.wantErr {
t.Errorf("makeBody() error = %v, wantErr %v", err, tt.wantErr)

if tt.wantErr {
if err == nil {
t.Error("期望错误但得到 nil")
}
return
}
if tt.body == nil {
if reader != nil {
t.Error("expected nil reader for nil body")
}

if err != nil {
t.Errorf("makeBody() 错误 = %v", err)
return
}
if reader == nil {
t.Error("expected non-nil reader")

if reader == nil && tt.want != "" {
t.Error("期望非空 reader 但得到 nil")
return
}

if reader != nil {
got, err := io.ReadAll(reader)
if err != nil {
t.Errorf("读取 body 失败: %v", err)
return
}

if string(got) != tt.want {
t.Errorf("makeBody() = %v, 期望 %v", string(got), tt.want)
}
}
})
}
}
Expand All @@ -72,48 +115,80 @@ func TestNewRequestWithContext(t *testing.T) {
tests := []struct {
name string
opts []Option
want func(*http.Request) bool
wantErr bool
}{
{
name: "basic request",
name: "基本请求",
opts: []Option{MethodGet, URL("http://example.com")},
want: func(r *http.Request) bool {
return r.Method == "GET" &&
r.URL.String() == "http://example.com"
},
},
{
name: "request with path",
name: "带路径参数",
opts: []Option{MethodGet, URL("http://example.com"), Path("/api"), Path("/v1")},
want: func(r *http.Request) bool {
return r.URL.Path == "/api/v1"
},
},
{
name: "request with query",
name: "带查询参数",
opts: []Option{MethodGet, URL("http://example.com"), Param("key", "value")},

want: func(r *http.Request) bool {
return r.URL.RawQuery == "key=value"
},
},
{
name: "request with headers",
opts: []Option{MethodGet, URL("http://example.com"), Header("Content-Type", "application/json")},
name: "带请求头",
opts: []Option{MethodGet, URL("http://example.com"), Header("X-Test", "test-value")},
want: func(r *http.Request) bool {
return r.Header.Get("X-Test") == "test-value"
},
},
{
name: "request with cookies",
name: "带Cookie",
opts: []Option{MethodGet, URL("http://example.com"), Cookie(http.Cookie{Name: "session", Value: "123"})},
want: func(r *http.Request) bool {
cookies := r.Cookies()
return len(cookies) == 1 &&
cookies[0].Name == "session" &&
cookies[0].Value == "123"
},
},
{
name: "无效URL",
opts: []Option{MethodGet, URL("://invalid"), Cookie(http.Cookie{Name: "session", Value: "123"})},
wantErr: true,
},
{
name: "无效body",
opts: []Option{MethodGet, URL("http://example.com"), Body(make(chan int))},
wantErr: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
options := newOptions(tt.opts)
req, err := NewRequestWithContext(context.Background(), options)
if (err != nil) != tt.wantErr {
t.Errorf("NewRequestWithContext() error = %v, wantErr %v", err, tt.wantErr)
ctx := context.Background()
req, err := NewRequestWithContext(ctx, newOptions(tt.opts))

if tt.wantErr {
if err == nil {
t.Error("期望错误但得到 nil")
}
return
}
if req == nil {
t.Error("expected non-nil request")

if err != nil {
t.Errorf("NewRequestWithContext() 错误 = %v", err)
return
}
// Verify request properties
if req.Method != options.Method {
t.Errorf("expected method %s, got %s", options.Method, req.Method)
}
if !strings.HasPrefix(req.URL.String(), options.URL) {
t.Errorf("expected URL to start with %s, got %s", options.URL, req.URL.String())

if !tt.want(req) {
t.Errorf("请求不符合预期条件")
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion response_writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ func TestResponseWriterRead(t *testing.T) {
// 测试读取完后的EOF
n, err = w.Read(buf)
if err != io.EOF {
t.Errorf("Expected EOF after reading all data, got %v", err)
t.Errorf("Expected EOF after reading all data, got n=%d, err=%v", n, err)
}
}

Expand Down
Loading