backend/pkg/library/cassandra/query_test.go

521 lines
11 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cassandra
import (
"testing"
"github.com/scylladb/gocqlx/v2/qb"
"github.com/stretchr/testify/assert"
)
func TestEq(t *testing.T) {
tests := []struct {
name string
column string
value any
validate func(*testing.T, Condition)
}{
{
name: "string value",
column: "name",
value: "Alice",
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, "Alice", binds["name"])
},
},
{
name: "int value",
column: "age",
value: 25,
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, 25, binds["age"])
},
},
{
name: "nil value",
column: "description",
value: nil,
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Nil(t, binds["description"])
},
},
{
name: "empty string",
column: "email",
value: "",
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, "", binds["email"])
},
},
{
name: "boolean value",
column: "active",
value: true,
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, true, binds["active"])
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cond := Eq(tt.column, tt.value)
assert.NotNil(t, cond)
tt.validate(t, cond)
})
}
}
func TestIn(t *testing.T) {
tests := []struct {
name string
column string
values []any
validate func(*testing.T, Condition)
}{
{
name: "string values",
column: "status",
values: []any{"active", "pending", "completed"},
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, []any{"active", "pending", "completed"}, binds["status"])
},
},
{
name: "int values",
column: "ids",
values: []any{1, 2, 3, 4, 5},
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, []any{1, 2, 3, 4, 5}, binds["ids"])
},
},
{
name: "empty slice",
column: "tags",
values: []any{},
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, []any{}, binds["tags"])
},
},
{
name: "single value",
column: "id",
values: []any{1},
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, []any{1}, binds["id"])
},
},
{
name: "mixed types",
column: "values",
values: []any{"string", 123, true},
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, []any{"string", 123, true}, binds["values"])
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cond := In(tt.column, tt.values)
assert.NotNil(t, cond)
tt.validate(t, cond)
})
}
}
func TestGt(t *testing.T) {
tests := []struct {
name string
column string
value any
validate func(*testing.T, Condition)
}{
{
name: "int value",
column: "age",
value: 18,
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, 18, binds["age"])
},
},
{
name: "float value",
column: "price",
value: 99.99,
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, 99.99, binds["price"])
},
},
{
name: "zero value",
column: "count",
value: 0,
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, 0, binds["count"])
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cond := Gt(tt.column, tt.value)
assert.NotNil(t, cond)
tt.validate(t, cond)
})
}
}
func TestLt(t *testing.T) {
tests := []struct {
name string
column string
value any
validate func(*testing.T, Condition)
}{
{
name: "int value",
column: "age",
value: 65,
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, 65, binds["age"])
},
},
{
name: "float value",
column: "price",
value: 199.99,
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, 199.99, binds["price"])
},
},
{
name: "negative value",
column: "balance",
value: -100,
validate: func(t *testing.T, cond Condition) {
cmp, binds := cond.Build()
assert.NotNil(t, cmp)
assert.Equal(t, -100, binds["balance"])
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cond := Lt(tt.column, tt.value)
assert.NotNil(t, cond)
tt.validate(t, cond)
})
}
}
func TestCondition_Build(t *testing.T) {
tests := []struct {
name string
cond Condition
validate func(*testing.T, qb.Cmp, map[string]any)
}{
{
name: "Eq condition",
cond: Eq("name", "test"),
validate: func(t *testing.T, cmp qb.Cmp, binds map[string]any) {
assert.NotNil(t, cmp)
assert.Equal(t, "test", binds["name"])
},
},
{
name: "In condition",
cond: In("ids", []any{1, 2, 3}),
validate: func(t *testing.T, cmp qb.Cmp, binds map[string]any) {
assert.NotNil(t, cmp)
assert.Equal(t, []any{1, 2, 3}, binds["ids"])
},
},
{
name: "Gt condition",
cond: Gt("age", 18),
validate: func(t *testing.T, cmp qb.Cmp, binds map[string]any) {
assert.NotNil(t, cmp)
assert.Equal(t, 18, binds["age"])
},
},
{
name: "Lt condition",
cond: Lt("price", 100),
validate: func(t *testing.T, cmp qb.Cmp, binds map[string]any) {
assert.NotNil(t, cmp)
assert.Equal(t, 100, binds["price"])
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmp, binds := tt.cond.Build()
tt.validate(t, cmp, binds)
})
}
}
func TestQueryBuilder_Where(t *testing.T) {
tests := []struct {
name string
condition Condition
validate func(*testing.T, *queryBuilder[testUser])
}{
{
name: "single condition",
condition: Eq("name", "Alice"),
validate: func(t *testing.T, qb *queryBuilder[testUser]) {
assert.Len(t, qb.conditions, 1)
},
},
{
name: "multiple conditions",
condition: In("status", []any{"active", "pending"}),
validate: func(t *testing.T, qb *queryBuilder[testUser]) {
// 添加多個條件
cond := In("status", []any{"active", "pending"})
qb.Where(Eq("name", "test"))
qb.Where(cond)
assert.Len(t, qb.conditions, 2)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 注意:這需要一個有效的 repository但我們可以測試鏈式調用
// 實際的執行需要資料庫連接
_ = tt
})
}
}
func TestQueryBuilder_OrderBy(t *testing.T) {
tests := []struct {
name string
column string
order Order
validate func(*testing.T, *queryBuilder[testUser])
}{
{
name: "ASC order",
column: "created_at",
order: ASC,
validate: func(t *testing.T, qb *queryBuilder[testUser]) {
assert.Len(t, qb.orders, 1)
assert.Equal(t, "created_at", qb.orders[0].column)
assert.Equal(t, ASC, qb.orders[0].order)
},
},
{
name: "DESC order",
column: "updated_at",
order: DESC,
validate: func(t *testing.T, qb *queryBuilder[testUser]) {
assert.Len(t, qb.orders, 1)
assert.Equal(t, "updated_at", qb.orders[0].column)
assert.Equal(t, DESC, qb.orders[0].order)
},
},
{
name: "multiple orders",
column: "name",
order: ASC,
validate: func(t *testing.T, qb *queryBuilder[testUser]) {
qb.OrderBy("created_at", DESC)
qb.OrderBy("name", ASC)
assert.Len(t, qb.orders, 2)
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 注意:這需要一個有效的 repository
_ = tt
})
}
}
func TestQueryBuilder_Limit(t *testing.T) {
tests := []struct {
name string
limit int
expected int
}{
{
name: "positive limit",
limit: 10,
expected: 10,
},
{
name: "zero limit",
limit: 0,
expected: 0,
},
{
name: "large limit",
limit: 1000,
expected: 1000,
},
{
name: "negative limit",
limit: -1,
expected: -1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 注意:這需要一個有效的 repository
_ = tt
})
}
}
func TestQueryBuilder_Select(t *testing.T) {
tests := []struct {
name string
columns []string
expected int
}{
{
name: "single column",
columns: []string{"name"},
expected: 1,
},
{
name: "multiple columns",
columns: []string{"name", "email", "age"},
expected: 3,
},
{
name: "empty columns",
columns: []string{},
expected: 0,
},
{
name: "duplicate columns",
columns: []string{"name", "name"},
expected: 2,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 注意:這需要一個有效的 repository
_ = tt
})
}
}
func TestQueryBuilder_Chaining(t *testing.T) {
t.Run("chain multiple methods", func(t *testing.T) {
// 注意:這需要一個有效的 repository
// 實際的執行需要資料庫連接
// 這裡只是展示測試結構
})
}
func TestQueryBuilder_Scan_ErrorCases(t *testing.T) {
tests := []struct {
name string
description string
}{
{
name: "nil destination",
description: "should return error when destination is nil",
},
{
name: "invalid query",
description: "should return error when query is invalid",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 注意:這需要 mock session 或實際的資料庫連接
_ = tt
})
}
}
func TestQueryBuilder_One_ErrorCases(t *testing.T) {
tests := []struct {
name string
description string
}{
{
name: "no results",
description: "should return ErrNotFound when no results found",
},
{
name: "query error",
description: "should return error when query fails",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 注意:這需要 mock session 或實際的資料庫連接
_ = tt
})
}
}
func TestQueryBuilder_Count_ErrorCases(t *testing.T) {
tests := []struct {
name string
description string
}{
{
name: "query error",
description: "should return error when query fails",
},
{
name: "ErrNotFound should return 0",
description: "should return 0 when ErrNotFound",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 注意:這需要 mock session 或實際的資料庫連接
_ = tt
})
}
}