conf/test/conf.yaml 열기: 해당 파일이나 디렉터리가 없습니다.
https://github.com/cloudwego/cwgo/issues/120
https://github.com/cloudwego/cwgo/issues/29
Kitex를 사용하여 생성된 코드에서 단위 테스트는 제목과 같이 오류를 반환합니다. 이 오류가 발생하는 이유는 biz/service
스프링 부트가 단위 테스트를 수행할 때 전체 스프링 환경을 로드해야 하는 것처럼 단위 테스트 방법에도 독립적인 단위 테스트 대신 완전한 프레임워크 테스트가 필요하기 때문입니다.
획득한 conf.yaml
소스 코드를 확인하세요.
func initConf() {
prefix := "conf"
confFileRelPath := filepath.Join(prefix, filepath.Join(GetEnv(), "conf.yaml"))
content, err := ioutil.ReadFile(confFileRelPath)
if err != nil {
panic(err)
}
conf = new(Config)
err = yaml.Unmarshal(content, conf)
if err != nil {
hlog.Error("parse yaml error - %v", err)
panic(err)
}
if err := validator.Validate(conf); err != nil {
hlog.Error("validate config error - %v", err)
panic(err)
}
conf.Env = GetEnv()
pretty.Printf("%+v\n", conf)
}
위 코드에서는 GetEnv()
메소드를 통해 yaml 구성 파일의 중간 경로를 가져오며, 메소드 본문은 다음과 같습니다.
func GetEnv() string {
e := os.Getenv("GO_ENV")
if len(e) == 0 {
return "test"
}
return e
}
위 방법은 go env 디렉토리를 구하는 방법으로, 본 프로젝트와는 관련이 없으며 수정이 필요합니다.
dev
당연히 여기에서 ,online
등test
의 환경을 시작해야 합니다. 이에 대해서는 다른 글에서 다루겠습니다. 여기서 프로젝트를 시작하겠습니다.
GetEnv()
먼저 하나를 작성test
하고 해당 디렉토리의 conf 파일에 구성을 작성하십시오.
위의 내용에 따라 구성한 후 다음과 같이 되어야 합니다.
prefix := "conf"
confFileRelPath := filepath.Join(prefix, filepath.Join("test", "conf.yaml"))
}
이 메소드를 호출할 때 합성된 경로는 conf/test/conf.yaml
너무나 당연하게도 찾을 수 없습니다.conf
디렉토리 외부에는 구조가 없습니다.。
이때는 conf.yaml
검색 위치를 절대 경로로 설정하기만 하면 어떤 파일을 사용하든 절대 디렉터리에서 구성 파일을 쿼리하고 오류가 보고되지 않도록 할 수 있습니다.
Go 언어는 os.Getwd()
절대 경로를 얻는 방법을 제공합니다.
이 메서드는 동적이므로 메서드가 있는 디렉터리를 가져오는 것이 아니라 메서드를 호출하는 파일이 있는 디렉터리를 가져옵니다. 따라서 메소드 호출 위치에 따라 경로가 변경되어야 하므로 이 메소드는 불가능합니다.
따라서 filepath.Abs()
파일의 절대 경로를 얻는 방법을 사용하십시오. 여기에서 conf의 절대 경로를 얻고 conf.yaml
경로를 설정할 수 있습니다.
.
현재 디렉터리를 나타냅니다.
그러나 이것은 작동하지 않습니다. 왜냐하면 go에서 얻은 경로는 모두 동적이고 os.GetWd()
or 의 캡슐화는 filepath.Abs()
형식적이며 값이 실제로 할당될 때만 실제로 호출되기 때문입니다. 다음과 같이
테스트 환경 주소가 되기 위해 테스트 환경에서 호출됩니다.
주 함수 호출은 주 함수 주소가 됩니다.
그렇다면 어떻게 해결해야 할까요?
에디터는 루트 경로를 얻을 때까지 경로를 파싱한 후, 루트 경로를 통해 구성 파일 경로를 구성하는데, 이렇게 하면 어떤 디렉토리를 호출하더라도 루트 경로를 먼저 얻은 후 구성 파일 경로를 구성하게 된다.
내 생각은 다음과 같습니다.
- conf 호출자의 절대 경로를 얻으십시오.
os.Getwd()
- go는 전체 프로젝트의 절대 경로를 얻을 수 없기 때문에, 프로젝트의 절대 경로를 얻기 위해서는 경로를 파싱해야 합니다.
filepath.Dir(currentDir)
상위 디렉터리를 가져오는 데 사용filepath.Base(currentDir)
획득한 마지막 디렉터리의 이름을 사용3
하고 프로젝트 루트와 비교합니다.- 같음은 경로가 절대 경로임을 나타냅니다.
- 임의의 디렉터리에서 호출 하면
1,2,3,4,5
절대 주소가 어떻게 변경되더라도 프로젝트 루트 디렉터리를 얻을 수 있습니다.- 루트 디렉터리(프로젝트 이름 비교는 구성 파일이나 기본 함수에서 얻을 수 있습니다. 코드에 하드 코딩할 생각은 마세요) [선택 사항]
그러면 수정된 conf initConf
코드는 다음과 같습니다.
func initConf() {
// 主函数为最外层函数,路径为根地址,其它路径调用只可能在其子目录下
// 获取调用者路径
fakepath,err := os.Getwd()
if err != nil{
log.Fatal(errors.New("获取调用者路径失败"))
panic(err)
}
// 循环比较路径的最后一位是否为根目录
// 如果是根目录就停止,循环超20次自动停止(没有目录有这么多层)
i := 0
for {
i++
if filepath.Base(fakepath) == "food_platform" {
// 这里的food_platform是最原始根目录路径名,也就是项目最外层文件名
break
}
fakepath = filepath.Dir(fakepath)
if i >= 20 {
log.Fatal(errors.New("获取调用者路径失败"))
panic(err)
}
}
prefix := fakepath + "/cms_commodity/api/conf"
// 获取配置文件路径
confFileRelPath := filepath.Join(prefix, filepath.Join("test","conf.yaml"))
content, err := ioutil.ReadFile(confFileRelPath)
if err != nil {
panic(err)
}
conf = new(Config)
err = yaml.Unmarshal(content, conf)
if err != nil {
klog.Error("parse yaml error - %v", err)
panic(err)
}
if err := validator.Validate(conf); err != nil {
klog.Error("validate config error - %v", err)
panic(err)
}
conf.Env = GetEnv()
pretty.Printf("%+v\n", conf)
}
위에서 실제 상황에 따라 수정해야 할 세 곳이 있습니다.
/test
여기에 작성된 정적 항목은os.Args
및flag
라이브러리를 사용하여 명령줄에서 얻을 수 있습니다.- 판단의 조건
food_platform
은 프로젝트 이름, 최상위 루트 프로젝트의 이름으로 이는 실제 상황에 맞게 수정이 필요하며 물론 설정 파일에 작성하거나 명령줄에서 얻을 수도 있습니다./cms_commodity/api/conf
코드에 적힌 내용으로 루트 디렉터리에서 설정 파일까지의 경로로, 프로젝트의 구조를 변경할 수 없도록 요구합니다.