unit-testinggogo-testinggomock

Golang how to test function that return channel type?


I try to test function StartP,
Expect that Start() should be called 1 times, Done() should be called 1 times

but I have trouble that test will block when run this step <-ps.Done()

I expect <-ps.Done() return nil

How can I test function that return chan type?

// production code

func (s *vService) StartP(ctx context.Context, reason string) error {

    ps, err := s.factory.CreateVService(ctx)
    if err != nil {
        return err
    }
    ps.Start(reason)

    err = <-ps.Done()   // code stop here to wait ? how can i test ?

    if err != nil {
        return err
    }
    return nil
}
// test code

func Test_StartP(t *testing.T) {
    mockCtrl := gomock.NewController(t)
    defer mockCtrl.Finish()

    mockPService := mockpservice.NewMockPInterface(mockCtrl)

    vService := &vService {
                      factory: &servicefactory.FakeServiceFactory{
                                 MockPService: mockPService
                               }
                    }

    mockPService.EXPECT().Start("reason").Times(1).Return()
    mockPService.EXPECT().Done().Times(1).DoAndReturn(func() chan error {
        return nil
    })

    err := vService.StartP(context.Background(), "reason")
    assert.Equal(t, nil, err)
}

I use gomock to mock the PServiceInterface

// interface

type PServiceInterface interface {
    Start(reason string)
    Done() <-chan error
}

gomock gen this function

func (m *MockProvisionServiceInterface) Done() <-chan error {
        m.ctrl.T.Helper()
        ret := m.ctrl.Call(m, "Done")
        ret0, _ := ret[0].(<-chan error)
        fmt.Println(ret0,".....mock Done()")
        return ret0
}

// I also try this

    mockProvisionService.EXPECT().Done().Times(1).DoAndReturn( func() chan error {
        fmt.Println("DoAndReturn...err nil")

        ch := make(chan error, 1)
        ch <- nil
        return ch
    })

Solution

  • I found the answer, root cause is DoAndReturn something wrong.

    Func type should be <-chan error, not chan error

     mockProvisionService.EXPECT().Done().Times(1).DoAndReturn( func() <-chan error{
                fmt.Println("DoAndReturn...err nil")
                ch := make(chan error, 1)
                ch <- nil
                return ch
            })