Golang中如何编写返回类型的测试
Golang中如何编写返回类型的测试 我一直在学习这门课程通过测试学习Go。我喜欢TDD的概念,但在编写自己的测试时遇到了困难。
我正在编写一个程序,该程序将从’.sql’文件加载查询,然后运行它并将结果存储为报告。
我不太确定该如何测试这个功能,我有一个如下所示的可运行函数,但测试无法通过…
函数
// LoadQuery retrieves .sql file from filesystem
func LoadQuery() {
// Load Query from file
content, err := ioutil.ReadFile("query.sql")
if err != nil {
log.Fatal("File not found")
}
// Convert Query to String
query := string(content[:])
return query
}
我的测试
func TestLoadQuery(t *testing.T) {
t.Run("load sql from file", func(t *testing.T) {
if LoadQuery() != string {
t.Error("Expected string")
}
})
}
更多关于Golang中如何编写返回类型的测试的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这段代码能编译通过吗?LoadQuery()函数返回的是字符串,但没有指定返回参数——这应该在编译时出现"too many arguments to return"错误而失败。
另外,如果你确实将LoadQuery()改为返回字符串,这个测试就多余了。但即使你想测试某个变量是否为特定类型(比如LoadQuery返回interface{}),也不应该用x != string这样的方式来测试。简单示例:https://play.golang.org/p/aGvCH8OkrWW
更多关于Golang中如何编写返回类型的测试的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
如果你指定了返回类型为 string,然后测试返回的变量是 string 类型,那么这种特定的测试就是多余的——编译器会保证在这种情况下返回类型始终是 string。除非你在该函数中返回一个字符串,否则应用程序将无法编译,因此这个测试实际上并没有测试任何内容。在你的 SQL 查询示例中,一个更有用的测试可能是结果不是空字符串(例如,如果你总是期望返回一个 SQL 查询),或者返回的 SQL 查询字符串始终是符合你目的的有效查询(我想这类似于你刚刚发布的第二个示例)。希望这说得通,如果还有不清楚的地方,请告诉我,我可以尝试用另一种方式解释。
是的,在我添加了返回类型为string之后,这段代码才能编译通过。
你能详细说明为什么这个测试会是多余的吗?难道测试不是始终必要的吗?
要为这个需求编写测试,即从文件中读取SQL语句并转换成字符串发送给数据库查询客户端……我遇到的问题是我生成报告的查询语句本身就有数千行。这是个问题,因为到目前为止我看到的测试都是用反引号来编写成功测试用例的,比如 select * from table。
话虽如此,也许我可以使用模式匹配表达式,这样测试用例就可以写成:
got := LoadQuery()
want := `%select%from%`
if got != want {
t.Error("file not sql")
}
感谢你的回复,非常感激任何能增进我对Go测试理解的进一步意见!😊
添加我的最终解决方案。欢迎进一步反馈,但我的问题已经得到解答,对此我很满意。
首先是我的代码:
package main
import (
"fmt"
"io/ioutil"
"log"
)
var err error
func main() {
fmt.Println(LoadQuery())
}
// LoadQuery retrieves .sql file from filesystem
func LoadQuery() string {
// Load Query from file
content, err := ioutil.ReadFile("code_checker.sql")
if err != nil {
log.Fatal("File not found")
}
// Convert Query to String
query := string(content[:])
return query
}
当我移除字节转字符串行并运行测试时,出现以下错误:
c:\dev\go\src\###\reporter.go:53:2: cannot use content (type []byte) as type string in return argument
FAIL ### [build failed]
Error: Tests failed.
使用字符串转换后的情况:
2018/08/21 14:15:46 File not found
FAIL 0.200s
Error: Tests failed.
以及我的测试:
package main
import (
"fmt"
"testing"
)
func TestLoadQuery(t *testing.T) {
t.Run("load sql from file", func(t *testing.T) {
// Test fails if either no file present or not string returned.
if len(LoadQuery()) > 0 {
fmt.Println("Empty String")
}
})
}
我认为这个测试可以改进的方式包括…理解如何为测试模拟文件。将测试文本更改为更符合惯例,也许这个测试的名称应该是"从文件加载字符串",因为这才是我们实际在做的事情。
您的测试无法通过是因为函数 LoadQuery 的返回类型声明不正确,并且测试中的断言方式有误。以下是具体问题和解决方案:
问题分析
- 函数返回类型不匹配:
LoadQuery函数在声明时没有指定返回类型,但实际代码中尝试返回query(字符串类型)。这会导致编译错误。 - 测试断言错误:在测试中,
LoadQuery() != string试图将函数返回值与类型string比较,这是无效的语法。应检查返回值是否为预期的字符串内容。
修正后的代码
函数修正
将 LoadQuery 函数修改为返回字符串类型,并处理错误而不是直接调用 log.Fatal(在测试中直接退出会中断测试流程)。返回错误可以让测试更灵活地验证不同情况。
// LoadQuery retrieves .sql file from filesystem and returns the query as a string.
func LoadQuery() (string, error) {
content, err := ioutil.ReadFile("query.sql")
if err != nil {
return "", err // 返回错误而不是终止程序
}
return string(content), nil
}
测试修正
测试应验证函数返回的字符串内容是否符合预期,并检查错误处理。使用 t.Helper() 标记辅助函数以在错误报告中提供更清晰的上下文。
func TestLoadQuery(t *testing.T) {
t.Run("load sql from file", func(t *testing.T) {
got, err := LoadQuery()
if err != nil {
t.Fatalf("Expected no error, but got: %v", err)
}
// 示例:验证返回的字符串非空且包含特定SQL关键字(根据实际文件内容调整)
if got == "" {
t.Error("Expected non-empty query string")
}
// 可选:检查具体内容,例如是否包含 "SELECT"
if !strings.Contains(got, "SELECT") {
t.Error("Expected query to contain 'SELECT'")
}
})
// 可选:测试文件不存在的情况
t.Run("file not found", func(t *testing.T) {
// 临时重命名或移除 "query.sql" 文件以模拟缺失情况
// 注意:在实际项目中,使用依赖注入或模拟文件系统会更可靠
originalName := "query.sql"
tempName := "query_temp.sql"
os.Rename(originalName, tempName)
defer os.Rename(tempName, originalName) // 测试后恢复文件
_, err := LoadQuery()
if err == nil {
t.Error("Expected error when file is missing")
}
})
}
关键点说明
- 返回类型和错误处理:函数应明确返回
(string, error),允许测试验证正常和错误情况。 - 测试内容匹配:通过检查返回字符串的实际内容(如非空或包含特定关键字)来确保功能正确。
- 文件操作测试:对于文件缺失的情况,通过临时修改文件系统状态来测试错误路径,但更健壮的方法是使用接口抽象文件操作(如
io.Reader),以便在测试中注入模拟依赖。
通过以上修正,您的测试将能够编译并通过,同时覆盖正常和异常场景。

