Skip to content
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ dumped_hertz_remote_config.json
/config/config.yaml
/config/config.yaml.bak
/k8s/config/configmap.yaml
coverage.txt
**/coverage.txt
**/coverage.out
**/coverage.html
ca-key
*.jks

Expand Down
54 changes: 54 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"errors"
"log"
"os"
"path/filepath"

"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
Expand Down Expand Up @@ -159,3 +160,56 @@ func GetLoggerLevel() string {
}
return Server.LogLevel
}

// InitForTest 专门用于测试环境的配置初始化
// 会读取config.example.yaml文件
func InitForTest(service string) error {
// 寻找项目根目录的config.example.yaml文件
configPath := findConfigFile("config.example.yaml")
if configPath == "" {
logger.Fatalf("config.InitForTest: config.example.yaml not found")
}

// 直接指定配置文件的完整路径
runtimeViper.SetConfigFile(configPath)

if err := runtimeViper.ReadInConfig(); err != nil {
logger.Fatalf("config.InitForTest: read config error: %v", err)
}
configMapping(service)

return nil
}

// findConfigFile 从当前目录开始向上查找配置文件
func findConfigFile(filename string) string {
// 首先尝试当前目录
currentDir, err := os.Getwd()
if err != nil {
return ""
}

// 向上查找直到找到文件或到达根目录
for {
configPath := filepath.Join(currentDir, "config", filename)
if _, err := os.Stat(configPath); err == nil {
return configPath
}

// 尝试直接在当前目录查找
configPath = filepath.Join(currentDir, filename)
if _, err := os.Stat(configPath); err == nil {
return configPath
}

// 向上一级目录
parentDir := filepath.Dir(currentDir)
if parentDir == currentDir {
// 已经到达根目录
break
}
currentDir = parentDir
}

return ""
}
8 changes: 8 additions & 0 deletions hack/docker-run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@

CONFIG_PATH="../config/config.yaml" # related to project folder

# 青果认证配置
QINGGUO_AUTH_KEY=""
QINGGUO_AUTH_PWD=""
QINGGUO_PROXY_ENABLED="false"

get_port() {
local server_name="$1"

Expand Down Expand Up @@ -78,6 +83,9 @@ start_container() {
--network fzu-helper \
-p $server_port:$server_port \
-e ETCD_ADDR="fzu-helper-etcd:2379" \
-e QINGGUO_AUTH_KEY="$QINGGUO_AUTH_KEY" \
-e QINGGUO_AUTH_PWD="$QINGGUO_AUTH_PWD" \
-e QINGGUO_PROXY_ENABLED="$QINGGUO_PROXY_ENABLED" \
--restart always \
$image
}
Expand Down
139 changes: 85 additions & 54 deletions internal/academic/service/get_credit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,66 +22,97 @@
"testing"

"github.com/bytedance/mockey"
"github.com/stretchr/testify/assert"
. "github.com/smartystreets/goconvey/convey"

"github.com/west2-online/fzuhelper-server/kitex_gen/model"
meta "github.com/west2-online/fzuhelper-server/pkg/base/context"
baseContext "github.com/west2-online/fzuhelper-server/pkg/base/context"
"github.com/west2-online/jwch"
)

func TestAcademicService_GetCredit(t *testing.T) {
type testCase struct {
name string
mockReturn []*jwch.CreditStatistics
mockError error
expectedResult []*jwch.CreditStatistics
expectingError bool
}

expectedResult := []*jwch.CreditStatistics{
{
Type: "Compulsory",
Gain: "4.0",
Total: "8.0",
},
}

testCases := []testCase{
{
name: "GetCreditSuccess",
mockReturn: expectedResult,
mockError: nil,
expectedResult: expectedResult,
},
{
name: "GetCreditFailure",
mockReturn: nil,
mockError: fmt.Errorf("get credit info fail"),
expectedResult: nil,
expectingError: true,
},
}

defer mockey.UnPatchAll()
for _, tc := range testCases {
mockey.PatchConvey(tc.name, t, func() {
mockey.Mock((*jwch.Student).GetCredit).Return(tc.mockReturn, tc.mockError).Build()
mockey.Mock(meta.GetLoginData).To(func(ctx context.Context) (*model.LoginData, error) {
return &model.LoginData{
Id: "1111111111111111111111111111111111",
Cookies: "",
}, nil
}).Build()
academicService := AcademicService{}
result, err := academicService.GetCredit()
if tc.expectingError {
assert.Nil(t, result)
assert.Error(t, err)
assert.Contains(t, err.Error(), "Get credit info fail")
} else {
assert.NoError(t, err)
assert.Equal(t, tc.expectedResult, result)
Convey("GetCredit", t, func() {

Check failure on line 33 in internal/academic/service/get_credit_test.go

View workflow job for this annotation

GitHub Actions / lint

unnecessary leading newline (whitespace)

Convey("should return error when user is not logged in", func() {
// Given: 未登录的用户上下文
ctx := context.Background()
service := &AcademicService{ctx: ctx}

// When: 尝试获取学分信息
result, err := service.GetCredit()

// Then: 应该返回登录错误
So(result, ShouldBeNil)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldContainSubstring, "Get login data fail")
})

Convey("should return error when remote service is unavailable", func() {
// Given: 已登录用户但远程服务不可用
testLoginData := &model.LoginData{
Id: "test_student_id",
Cookies: "test_session=abc123",
}

getCreditPatch := mockey.Mock((*jwch.Student).GetCredit).Return(
nil, fmt.Errorf("network connection failed"),
).Build()
defer getCreditPatch.UnPatch()

ctx := baseContext.WithLoginData(context.Background(), testLoginData)
service := &AcademicService{ctx: ctx}

// When: 尝试获取学分信息
result, err := service.GetCredit()

// Then: 应该返回网络错误
So(result, ShouldBeNil)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldContainSubstring, "Get credit info fail")
})

Convey("should return credit statistics when request is successful", func() {
// Given: 已登录用户且系统正常
testLoginData := &model.LoginData{
Id: "222200311",
Cookies: "ASP.NET_SessionId=lzs1t42mpkml4ag2jrxvib4z",
}

expectedCreditStats := []*jwch.CreditStatistics{
{
Type: "公共基础必修课",
Gain: "29.5",
Total: "32",
},
{
Type: "学科基础必修课",
Gain: "54",
Total: "54",
},
}

getCreditPatch := mockey.Mock((*jwch.Student).GetCredit).Return(
expectedCreditStats, nil,
).Build()
defer getCreditPatch.UnPatch()

ctx := baseContext.WithLoginData(context.Background(), testLoginData)
service := &AcademicService{ctx: ctx}

// When: 获取学分信息
result, err := service.GetCredit()

// Then: 应该返回正确的学分统计数据
So(err, ShouldBeNil)
So(result, ShouldNotBeNil)
So(len(result), ShouldEqual, 2)

So(result[0].Type, ShouldEqual, "公共基础必修课")
So(result[0].Gain, ShouldEqual, "29.5")
So(result[0].Total, ShouldEqual, "32")

So(result[1].Type, ShouldEqual, "学科基础必修课")
So(result[1].Gain, ShouldEqual, "54")
So(result[1].Total, ShouldEqual, "54")
})
}
})
}
Loading
Loading