简体   繁体   中英

Unit testing of a function that starts a go routine inside it

I have a codebase that is roughly as follows

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")
}

And I wrote unit tests as something similar to this.

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.

All tests are successful. But when executing the command go test -v , I saw multiple places in the code where the program panicked and gave invalid memory address or nil pointer dereference . I checked the code in debug mode and realized that the issue is with impl.GoRoutineWaitgroup.Add(1) in method validateMyFunction and when I commented out go validateMyFunction(a,b) and ran tests again, there were no panics in the logs. So How do I solve this issue? How to handle unit tests of functions where we start a goroutine from inside ( as in this case )?

You need initialize value to GoRoutineWaitgroup field.

ms := &Service{GoRoutineWaitgroup: &sync.WaitGroup{}}

Or remove pointer from definition

type Service struct {
    Repo                 repo 
    GoRoutineWaitgroup   sync.WaitGroup
}

Also I do not see waiting for Wait Group in your code. Something like ms.GoRoutineWaitgroup.Wait() and you need to move impl.GoRoutineWaitgroup.Add(1) to MyFunction from validateMyFunction otherwise the code in validateMyFunction will not be called

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM