skip to content
Alvin Lucillo

Resetting expectations

/ 2 min read

You can use Unset to remove the expectations on a given call. This is useful if you have a shared mock due to reasons like expensive setup or dependent tests.

main_test.go

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

	mockProc := servicemock.NewProcessor(t)
	mockLog := servicemock.NewLogger(t)
	mockLog.On("Errorf", mock.Anything, mock.Anything).Return().Maybe()

	tests := []struct {
		name    string
		videoID string
	}{
		{name: "first", videoID: "vid-1"},
		{name: "second", videoID: "vid-2"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			// Reuse the same mock across subtests (assume expensive setup),
			// then remove only this expectation so the next subtest starts clean.
			call := mockProc.On("Download", mock.Anything, tt.videoID).Return([]byte("raw"), nil).Once()
			defer call.Unset()

			got, err := DownloadVideo(ctx, mockProc, mockLog, tt.videoID)
			require.NoError(t, err)
			require.Equal(t, []byte("raw"), got)

			mockProc.AssertExpectations(t)
		})
	}
}

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
}

Note: mocked object results are omitted.