generated by Claude-3.7-Sonnet

This commit is contained in:
2025-03-28 22:27:08 +08:00
commit fdde34e1f0
13 changed files with 1581 additions and 0 deletions

View File

@@ -0,0 +1,331 @@
package search
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
)
func TestSearchPodcasts_EmptyTerm(t *testing.T) {
// 创建iTunes搜索提供者
provider := NewITunesProvider()
// 使用空搜索词调用SearchPodcasts
result, err := provider.SearchPodcasts("", nil)
// 验证返回错误
if err == nil {
t.Error("期望返回错误,但没有")
}
// 验证错误消息
expectedErrMsg := "搜索词不能为空"
if err.Error() != expectedErrMsg {
t.Errorf("期望错误消息为 %q但得到 %q", expectedErrMsg, err.Error())
}
// 验证结果为nil
if result != nil {
t.Errorf("期望结果为nil但得到 %+v", result)
}
}
func TestSearchPodcasts_SuccessfulSearch(t *testing.T) {
// 创建测试服务器
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 验证请求方法
if r.Method != http.MethodGet {
t.Errorf("期望请求方法为GET但得到 %s", r.Method)
}
// 验证请求路径
if r.URL.Path != "/search" {
t.Errorf("期望请求路径为/search但得到 %s", r.URL.Path)
}
// 验证查询参数
query := r.URL.Query()
if query.Get("term") != "golang" {
t.Errorf("期望term参数为golang但得到 %s", query.Get("term"))
}
if query.Get("entity") != "podcast" {
t.Errorf("期望entity参数为podcast但得到 %s", query.Get("entity"))
}
if query.Get("media") != "podcast" {
t.Errorf("期望media参数为podcast但得到 %s", query.Get("media"))
}
// 返回模拟响应
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
// 创建模拟响应数据
response := map[string]interface{}{
"resultCount": 2,
"results": []map[string]interface{}{
{
"collectionId": 1234567890,
"collectionName": "Go编程语言",
"artistName": "Go开发者",
"feedUrl": "https://example.com/feed1",
"artworkUrl100": "https://example.com/artwork1_100.jpg",
"artworkUrl600": "https://example.com/artwork1_600.jpg",
"genres": []string{"Technology", "Education"},
},
{
"collectionId": 9876543210,
"collectionName": "Golang讨论",
"artistName": "Golang爱好者",
"feedUrl": "https://example.com/feed2",
"artworkUrl100": "https://example.com/artwork2_100.jpg",
"artworkUrl600": "https://example.com/artwork2_600.jpg",
"genres": []string{"Technology"},
},
},
}
// 将响应数据编码为JSON并写入响应
json.NewEncoder(w).Encode(response)
}))
defer server.Close()
// 创建iTunes搜索提供者并设置测试服务器URL
provider := &ITunesProvider{
SearchAPIEndpoint: server.URL,
FeedAPIEndpoint: "https://itunes.apple.com",
GenresMap: initITunesGenres(),
Client: &http.Client{Timeout: 20 * time.Second},
}
// 调用SearchPodcasts
result, err := provider.SearchPodcasts("golang", nil)
// 验证没有错误
if err != nil {
t.Fatalf("期望没有错误,但得到 %v", err)
}
// 验证结果
if result == nil {
t.Fatal("期望结果不为nil但得到nil")
}
// 验证结果计数
if result.ResultCount != 2 {
t.Errorf("期望结果计数为2但得到 %d", result.ResultCount)
}
// 验证结果成功标志
if !result.Successful {
t.Error("期望结果成功标志为true但得到false")
}
// 验证结果项目数量
if len(result.Items) != 2 {
t.Errorf("期望结果项目数量为2但得到 %d", len(result.Items))
}
// 验证第一个结果项目
item1 := result.Items[0]
if item1.CollectionID != 1234567890 {
t.Errorf("期望第一个项目的CollectionID为1234567890但得到 %d", item1.CollectionID)
}
if item1.Title != "Go编程语言" {
t.Errorf("期望第一个项目的Title为'Go编程语言',但得到 %s", item1.Title)
}
if item1.Author != "Go开发者" {
t.Errorf("期望第一个项目的Author为'Go开发者',但得到 %s", item1.Author)
}
if item1.FeedURL != "https://example.com/feed1" {
t.Errorf("期望第一个项目的FeedURL为'https://example.com/feed1',但得到 %s", item1.FeedURL)
}
if item1.ArtworkURL != "https://example.com/artwork1_100.jpg" {
t.Errorf("期望第一个项目的ArtworkURL为'https://example.com/artwork1_100.jpg',但得到 %s", item1.ArtworkURL)
}
if item1.ArtworkURL600 != "https://example.com/artwork1_600.jpg" {
t.Errorf("期望第一个项目的ArtworkURL600为'https://example.com/artwork1_600.jpg',但得到 %s", item1.ArtworkURL600)
}
if len(item1.Genres) != 2 || item1.Genres[0] != "Technology" || item1.Genres[1] != "Education" {
t.Errorf("期望第一个项目的Genres为[Technology, Education],但得到 %v", item1.Genres)
}
// 验证第二个结果项目
item2 := result.Items[1]
if item2.CollectionID != 9876543210 {
t.Errorf("期望第二个项目的CollectionID为9876543210但得到 %d", item2.CollectionID)
}
if item2.Title != "Golang讨论" {
t.Errorf("期望第二个项目的Title为'Golang讨论',但得到 %s", item2.Title)
}
}
func TestSearchPodcasts_WithOptions(t *testing.T) {
// 创建测试服务器
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 验证查询参数
query := r.URL.Query()
// 验证基本参数
if query.Get("term") != "golang" {
t.Errorf("期望term参数为golang但得到 %s", query.Get("term"))
}
// 验证选项参数
if query.Get("country") != "cn" {
t.Errorf("期望country参数为cn但得到 %s", query.Get("country"))
}
if query.Get("genreId") != "1318" { // Technology的ID
t.Errorf("期望genreId参数为1318但得到 %s", query.Get("genreId"))
}
if query.Get("attribute") != "titleTerm" {
t.Errorf("期望attribute参数为titleTerm但得到 %s", query.Get("attribute"))
}
if query.Get("limit") != "10" {
t.Errorf("期望limit参数为10但得到 %s", query.Get("limit"))
}
if query.Get("language") != "zh-cn" {
t.Errorf("期望language参数为zh-cn但得到 %s", query.Get("language"))
}
if query.Get("explicit") != "No" {
t.Errorf("期望explicit参数为No但得到 %s", query.Get("explicit"))
}
// 返回模拟响应
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
// 创建模拟响应数据
response := map[string]interface{}{
"resultCount": 1,
"results": []map[string]interface{}{
{
"collectionId": 1234567890,
"collectionName": "Go编程语言",
"artistName": "Go开发者",
"feedUrl": "https://example.com/feed1",
"artworkUrl100": "https://example.com/artwork1_100.jpg",
"artworkUrl600": "https://example.com/artwork1_600.jpg",
"genres": []string{"Technology"},
},
},
}
// 将响应数据编码为JSON并写入响应
json.NewEncoder(w).Encode(response)
}))
defer server.Close()
// 创建iTunes搜索提供者并设置测试服务器URL
provider := &ITunesProvider{
SearchAPIEndpoint: server.URL,
FeedAPIEndpoint: "https://itunes.apple.com",
GenresMap: initITunesGenres(),
Client: &http.Client{Timeout: 20 * time.Second},
}
// 创建搜索选项
options := &SearchOptions{
Country: "cn",
Genre: "Technology",
Attribute: "titleTerm",
Limit: 10,
Language: "zh-cn",
Explicit: false,
}
// 调用SearchPodcasts
result, err := provider.SearchPodcasts("golang", options)
// 验证没有错误
if err != nil {
t.Fatalf("期望没有错误,但得到 %v", err)
}
// 验证结果
if result == nil {
t.Fatal("期望结果不为nil但得到nil")
}
// 验证结果计数
if result.ResultCount != 1 {
t.Errorf("期望结果计数为1但得到 %d", result.ResultCount)
}
// 验证结果项目数量
if len(result.Items) != 1 {
t.Errorf("期望结果项目数量为1但得到 %d", len(result.Items))
}
}
func TestSearchPodcasts_APIError(t *testing.T) {
// 创建测试服务器,返回错误状态码
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
}))
defer server.Close()
// 创建iTunes搜索提供者并设置测试服务器URL
provider := &ITunesProvider{
SearchAPIEndpoint: server.URL,
FeedAPIEndpoint: "https://itunes.apple.com",
GenresMap: initITunesGenres(),
Client: &http.Client{Timeout: 20 * time.Second},
}
// 调用SearchPodcasts
result, err := provider.SearchPodcasts("golang", nil)
// 验证返回错误
if err == nil {
t.Error("期望返回错误,但没有")
}
// 验证错误消息包含状态码
expectedErrMsg := "API请求失败状态码: 500"
if err.Error() != expectedErrMsg {
t.Errorf("期望错误消息包含 %q但得到 %q", expectedErrMsg, err.Error())
}
// 验证结果为nil
if result != nil {
t.Errorf("期望结果为nil但得到 %+v", result)
}
}
func TestSearchPodcasts_InvalidJSON(t *testing.T) {
// 创建测试服务器返回无效的JSON
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"resultCount": 1, "results": [invalid json]`))
}))
defer server.Close()
// 创建iTunes搜索提供者并设置测试服务器URL
provider := &ITunesProvider{
SearchAPIEndpoint: server.URL,
FeedAPIEndpoint: "https://itunes.apple.com",
GenresMap: initITunesGenres(),
Client: &http.Client{Timeout: 20 * time.Second},
}
// 调用SearchPodcasts
result, err := provider.SearchPodcasts("golang", nil)
// 验证返回错误
if err == nil {
t.Error("期望返回错误,但没有")
}
// 验证错误消息包含解析失败
if err != nil && err.Error() != "解析响应失败: invalid character 'i' looking for beginning of value" {
t.Errorf("期望错误消息包含解析失败,但得到 %q", err.Error())
}
// 验证结果为nil
if result != nil {
t.Errorf("期望结果为nil但得到 %+v", result)
}
}