skip to content
Alvin Lucillo

Asserting if a method is or is not called

/ 2 min read

You can specifically check if a method is or is not called with specific arguments with AssertCalled and AssertNotCalled.

main.go

//go:generate mockery --name=Processor --dir=. --output=./mocks --outpkg=servicemock --case=snake
//go:generate mockery --name=Logger --dir=. --output=./mocks --outpkg=servicemock --case=snake

// ...

type Processor interface {
	Download(ctx context.Context, videoID string) ([]byte, error)
}

type Logger interface {
	Errorf(format string, args ...any)
}


func DownloadVideo(ctx context.Context, p Processor, log Logger, videoID string) ([]byte, error) {
	if videoID == "" {
		err := fmt.Errorf("videoID must be non-empty")
		log.Errorf("download failed: %v", err)
		return nil, err
	}
	data, err := p.Download(ctx, videoID)
	if err != nil {
		log.Errorf("download failed: %v", err)
		return nil, err
	}
	return data, nil
}

main_test.go

func TestDownloadVideo_AssertCalled(t *testing.T) {
	ctx := context.Background()

	tests := []struct {
		name     string
		videoID  string
		downErr  error
		wantErr  bool
		wantData []byte
		wantLog  bool
	}{
		{name: "happy_path", videoID: "vid-123", downErr: nil, wantErr: false, wantData: []byte("raw"), wantLog: false},
		{name: "download_error", videoID: "vid-123", downErr: errors.New("network"), wantErr: true, wantData: nil, wantLog: true},
		{name: "missing_id", videoID: "", downErr: nil, wantErr: true, wantData: nil, wantLog: true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			mockProc := servicemock.NewProcessor(t)
			mockLog := servicemock.NewLogger(t)

			mockLog.On("Errorf", mock.Anything, mock.Anything).Return().Maybe()

			if tt.videoID != "" {
				mockProc.On("Download", mock.Anything, tt.videoID).Return(tt.wantData, tt.downErr).Once()
			}

			got, err := DownloadVideo(ctx, mockProc, mockLog, tt.videoID)
			if tt.wantErr {
				require.Error(t, err)
			} else {
				require.NoError(t, err)
				require.Equal(t, tt.wantData, got)
			}

			if tt.wantLog {
				mockLog.AssertCalled(t, "Errorf", "download failed: %v", mock.Anything)
			} else {
				mockLog.AssertNotCalled(t, "Errorf", mock.Anything, mock.Anything)
			}
		})
	}
}

Note: mocked object results are omitted.