【Go语言入门教程】单元测试时同一个包下不同文件函数调用报错为 `undefined`



单元测试时同一个包下不同文件函数调用报错为 undefined 的问题

1. 背景知识

在 Terminal 终端命令行中,使用 go test 指令执行单元测试,所有以 _test.go 结尾的代码内以 Test 开头的函数会自动被执行。

go test -v hello_test.go

其中,-v 可以让测试时显示详细的流程信息。

2. 问题描述

单元测试的目录结构如下图所示:

image-20220518132408063

hello.go 代码:

package hello

func Hello() string {
   return "Hello, world."
}

hello_test.go 代码:

package hello

import "testing"

func TestHello(t *testing.T) {
   want := "Hello, world."
   if got := Hello(); got != want {
      t.Errorf("Hello() = %q, want %q", got, want)
   }
}

测试代码第 7 行中,调用了源代码的 Hello() 函数。如果直接运行单元测试,则测试不通过:

image-20220518132645217

提示我们,undefined: Hello 。即 Hello 函数未定义。

3. 原因

【原因】出现上述错误很大可能是当前项目运行在 GOPATH 模式下。在 GOPATH 模式下,go test 会为指定的源码文件生成一个虚拟代码包 “command-line-arguments”,而 hello_test.go 调用了 hello.go 中的 Hello() 函数并不属于代码包 “command-line-arguments” ,编译不通过,错误自然就产生了。

因此解决方式有两种:

  • 放弃使用 GOPATH 模式,改用 go mod 模式 (实际开发中使用最多,依赖管理很方便) 。
  • 坚持使用 GOPATH 模式,更改编译指令。

4. 解决方法一:关闭GOPATH,使用go mod

4.1 设置GO111MODULE

Win + R 输入 cmd 打开命令行,输入:

go env

即可看到 GO111MODULE (默认情况是空的):
image-20220518162705957

GO111MODULE 有三个值:off、on 和 auto (默认值)

  • GO111MODULE=off :go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。
  • GO111MODULE=on :go命令行会使用modules,而一点也不会去GOPATH目录下查找。
  • GO111MODULE=auto :默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
    • 当前目录在GOPATH/src之外且该目录包含go.mod文件
    • 当前文件在包含go.mod文件的目录下面。

【注】

  • 在使用go module时,GOPATH是无意义的。不过它仍然会把下载的依赖存储在 $GOPATH/pkg/mod 中,也会把 go install 的结果放在 $GOPATH/bin 中。
  • 当module功能启用时,依赖包的存放位置变更为 $GOPATH/pkg 。允许同一个package多个版本并存,且多个项目可以共享缓存的module。

设置的命令如下:

go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct

可在命令行中输入:go env 查看 GO111MODULE=on

4.2 清空所有GOPATH

开启 go mod 之后,并不能与 GOPATH 共存。必须把项目从 GOPATH 中移除,否则会报 $GOPATH/go.mod exists but should not 的错误。

在 Goland 中,移除项目所有 GOPATH 的操作如下:

image-20220518160417108
清空 GOPATH 之后,在单元测试模式下,同一个包下不同文件函数调用报错为 undefined 的问题也会解决。

4.3 在新项目中创建go mod

打开Windows终端命令行,cd 到新项目的文件夹目录。输入命令:

go mod init XXX(你的文件夹名称)

成功创建 go.mod 文件如下所示:
image-20220518102424712

4.4 执行单元测试

在所有相关的 .go 文件的同一个目录下 (在本例中,hello_test.go 和被调用的 hello.go 都在同一个目录 src 下),直接输入指令:

$ go test
//或
$ go test -v

即可直接执行测试:
image-20220518161414729
单元测试成功。

5. 解决方法二:坚持GOPATH模式,改变测试命令

如果你有特殊原因仍然坚持使用 GOPATH 模式,解决方案如下:
使用 Terminal 命令行的 go test 指令,加上要调用的文件 hello.go 。如下代码所示:

//进入测试文件所在的目录
$ cd src
//执行整个测试文件和调用到的文件
$ go test -v hello_test.go hello.go

输出:

=== RUN   TestHello
--- PASS: TestHello (0.00s)
PASS
ok      command-line-arguments  0.054s

测试成功。

image-20220518133455392

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自牧君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值