open conf/test/conf.yaml: no such file or directory
https://github.com/cloudwego/cwgo/issues/120
https://github.com/cloudwego/cwgo/issues/29
在使用Kitex生成的代码中,单元测试时回报错,如标题所示。出现该错的原因是,biz/service
单元测试方法同样需要完全的框架测试,而不是独立的单元测试,就像spring boot在进行单元测试时,需要加载整个的spring环境。
看到获取conf.yaml
的源码:
go
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)
}
调用该方法时默认会中当前目录下按照设置的位置查找配置文件,而配置文件实在根目录下,所以显然是找不到的。
此时只需要将查找conf.yaml
的位置设置为绝对的路径,这样不管在那个文件下使用单元测试,配置文件的修改都是从绝对目录查询,就不会报错找不到了。
需要注意的
conf.go
虽然是在[project]/conf
下,但是代码中确实动态变化的,也就是谁调用conf.go
的initconf
方法,获取的就是调用者当前的路径。
以下有三个获取路径的方法请选择合适的应用:
go
package main
import (
"fmt"
"os"
"path/filepath"
)
func main() {
// 获取当前工作目录的绝对路径
currentDir, err := os.Getwd()
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Current working directory:", currentDir)
// 获取当前文件的绝对路径
currentFile, err := os.Executable()
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Current executable file:", currentFile)
// 获取当前项目根目录的绝对路径
projectRoot := filepath.Dir(currentFile)
fmt.Println("Project root directory:", projectRoot)
}
小编的想法是:
- 获取conf调用者的绝对路径
os.Getwd()
- 由于go无法获取整个项目的绝对路径,那么就需要对路径解析获取项目绝对路径
- 使用
filepathDir(currentDir)
获取上一级目录- 使用
filepath.Base(currentDir)
获取3
的最后一个目录的名称,并与项目根目录比较- 相等就说明该路径为绝对路径
- 通过
1,2,3,4,5
不论在任何目录调用,不论绝对地址如何变化,都可以获取项目根目录- 根目录(项目名的比较可以从配置文件,或者从main函数得到,不要想我一些写死在代码中) 【可选】
那么修改后的conf的initConf
代码如下:
go
func initConf() {
//prefix := "conf"
//confFileRelPath := filepath.Join(prefix, filepath.Join(GetEnv(), "conf.yaml"))
// configuration the absolute path of conf file
currentDir ,err := os.Getwd()
// Go语言并知道那个是整个项目的根路径,需要人为判断
for{
currentDir = filepath.Dir(currentDir)
// 该项目名可在配置文件获取
if filepath.Base(currentDir) == "food_platform"{break}
}
confFileRelPath := currentDir + "/conf/test/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)
}
/test
和food_platform
都可以从main函数中定义。甚至再创建一个yaml文件作为这两个的配置文件都行。