对在其中启动 go 例程的函数进行单元测试
Posted
技术标签:
【中文标题】对在其中启动 go 例程的函数进行单元测试【英文标题】:Unit testing of a function that starts a go routine inside it 【发布时间】:2021-12-28 19:24:17 【问题描述】:我的代码库大致如下
type Service struct
Repo repo // An interface that contains both FunctionOne and FunctionTwo
GoRoutineWaitgroup *sync.WaitGroup
func (impl *Service) MyFunction(s string) bool
a := impl.Repo.FunctionOne()
b := impl.Repo.FunctionTwo()
fmt.Println("Executed Function One and Function two")
go impl.validateMyFunction(a,b)
return true
func (impl *Service) validateMyFunction(a string,b string)
defer helpers.PanicHandler()
impl.GoRoutineWaitgroup.Add(1)
defer impl.GoRoutineWaitgroup.Done()
fmt.Println("a and b are validated")
而且我编写的单元测试与此类似。
func TestMyFunction(t *testing.T)
ms := &Service
test := []struct
input string
output bool
case string
"a", true, sample
for _, test := range tests
t.Run(test.case, func(t *testing.T)
mockRepo := new(mockrepo.Repo) // mockRepo contains mocks of original repo layer methods generated using mockery for testing purposes
mockRepo.On("FunctionOne")
mockRepo.On("FunctionTwo")
ms.Repo = mockRepo
op := ms.MyFunction(test.input)
assert.Equal(t, test.Output, op)
)
// Please keep in mind that this is not my actual code, but just a basic structure.
所有测试都成功。但是在执行命令go test -v
时,我看到代码中有多个地方出现程序恐慌并给出invalid memory address or nil pointer dereference
。我在调试模式下检查了代码,发现问题出在方法validateMyFunction
中的impl.GoRoutineWaitgroup.Add(1)
上,当我注释掉go validateMyFunction(a,b)
并再次运行测试时,日志中没有出现恐慌。那么我该如何解决这个问题呢?如何处理我们从内部启动 goroutine 的函数的单元测试(如本例所示)?
【问题讨论】:
您的WaitGroup
在示例代码中是nil
。没有任何东西可以初始化它。
【参考方案1】:
您需要将值初始化为GoRoutineWaitgroup
字段。
ms := &ServiceGoRoutineWaitgroup: &sync.WaitGroup
或者从定义中删除指针
type Service struct
Repo repo
GoRoutineWaitgroup sync.WaitGroup
我也没有在您的代码中看到等待等待组。像ms.GoRoutineWaitgroup.Wait()
这样的东西,你需要将 impl.GoRoutineWaitgroup.Add(1) 从validateMyFunction
移动到MyFunction
,否则validateMyFunction
中的代码将不会被调用
【讨论】:
做到了。仍然遇到同样的问题。在做op := ms.MyFunction(test.input)
之前我们需要做什么吗?
也许你在存储库的某个地方有错误。我删除了存储库,因为我没有其实现的详细信息,您需要将 impl.GoRoutineWaitgroup.Add(1)
移动到 MyFunction
。我做了一个样本试试play.golang.org/p/PR-_u8uI-wY以上是关于对在其中启动 go 例程的函数进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章