package app import ( "context" "sync" "testing" "time" "go.uber.org/zap" ) type mockTaskPollable struct { refreshFunc func(ctx context.Context) error callCount int mu sync.Mutex } func (m *mockTaskPollable) RefreshStaleTasks(ctx context.Context) error { m.mu.Lock() defer m.mu.Unlock() m.callCount++ if m.refreshFunc != nil { return m.refreshFunc(ctx) } return nil } func (m *mockTaskPollable) getCallCount() int { m.mu.Lock() defer m.mu.Unlock() return m.callCount } func TestTaskPoller_StartStop(t *testing.T) { mock := &mockTaskPollable{} logger := zap.NewNop() poller := NewTaskPoller(mock, 1*time.Second, logger) poller.Start(context.Background()) time.Sleep(100 * time.Millisecond) poller.Stop() // No goroutine leak — Stop() returned means wg.Wait() completed. } func TestTaskPoller_RefreshesStaleTasks(t *testing.T) { mock := &mockTaskPollable{} logger := zap.NewNop() poller := NewTaskPoller(mock, 50*time.Millisecond, logger) poller.Start(context.Background()) defer poller.Stop() time.Sleep(300 * time.Millisecond) if count := mock.getCallCount(); count < 1 { t.Errorf("expected RefreshStaleTasks to be called at least once, got %d", count) } } func TestTaskPoller_StopsCleanly(t *testing.T) { mock := &mockTaskPollable{} logger := zap.NewNop() poller := NewTaskPoller(mock, 1*time.Second, logger) poller.Start(context.Background()) poller.Stop() // No panic and WaitGroup is done — Stop returned successfully. }