【问题标题】:Unit testing of a function that starts a go routine inside it对在其中启动 go 例程的函数进行单元测试
【发布时间】: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。没有任何东西可以初始化它。

标签: unit-testing go concurrency goroutine waitgroup


【解决方案1】:

您需要将值初始化为GoRoutineWaitgroup 字段。

ms := &Service{GoRoutineWaitgroup: &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
猜你喜欢
  • 2021-07-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-22
  • 1970-01-01
  • 2012-01-08
  • 2015-08-26
  • 2017-06-21
相关资源
最近更新 更多