Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use Gock with Parallel tests #117

Open
sazzer opened this issue Mar 29, 2024 · 2 comments
Open

How to use Gock with Parallel tests #117

sazzer opened this issue Mar 29, 2024 · 2 comments

Comments

@sazzer
Copy link

sazzer commented Mar 29, 2024

I'll openly admit I'm not the most proficient Go user. As such, I make heavy use of tools like golangci-lint to validate my code.

One thing this constantly flags up is when I forget t.Parallel() in my tests. However, I've also noticed that if I am using this then my gock-based tests fail.

For example:

package application_test

import (
	"net/http"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"gopkg.in/h2non/gock.v1"
)

func TestSimple(t *testing.T) {
	t.Parallel()

	defer gock.Off()

	gock.New("http://foo.com").
		Get("/bar").
		Reply(200)

	res, err := http.Get("http://foo.com/bar")

	require.NoError(t, err)
	assert.Equal(t, http.StatusOK, res.StatusCode)

	res.Body.Close()

	assert.True(t, gock.IsDone())
}

func TestSimple2(t *testing.T) {
	t.Parallel()

	defer gock.Off()

	gock.New("http://foo.com").
		Get("/bar").
		Reply(400)

	res, err := http.Get("http://foo.com/bar")

	require.NoError(t, err)
	assert.Equal(t, http.StatusBadRequest, res.StatusCode)

	res.Body.Close()

	assert.True(t, gock.IsDone())
}

This test file will sometimes pass, and will sometimes fail. And that's not surprising, because Gock has a bunch of static state that's shared between tests, and the tests are running in parallel.

Obviously removing t.Parallel() will make this work, but that seems a shame. I've also seen a suggestion of writing a TestMain() function that does all of the Gock work, but that also seems overly complicated for what's needed.

Are there any other recommended ways of doing tests like this?

Cheers

@nash567
Copy link

nash567 commented May 12, 2024

@sazzer, one workaround you can do is to create separate gock request instances for each test case and flush it off when the test case is executed.

eg.

type institution struct { ID string ShortName string }

type institutionResponse struct { Institutions []institution }

func NewTestGock() (*gock.Request, string) { baseURL := "https://localhost:63564" return gock.New(baseURL), baseURL }

`
func TestClient_Get(t *testing.T) {
t.Parallel()
expectedResp := institutionResponse{
Institutions: []institution{
{ID: "1033", ShortName: "CommBank"}},
}

type args struct {
	ctx  context.Context
	path string
}
tests := []struct {
	name    string
	args    args
	want    []byte
	wantErr bool
}{
	{
		name: "Success",
		args: args{
			ctx:  metadata.NewOutgoingContext(context.Background(), metadata.Pairs(interceptors.AuthMetadataKey, "token-value")),
			path: "v1/Finances/institutions",
		},
		want: func() []byte {
			data, _ := json.Marshal(expectedResp)
			return data
		}(),
		wantErr: false,
	},
	{
		name: "Unauthorized",
		args: args{
			ctx:  context.Background(),
			path: "v1/Finances/institutions",
		},
		want:    nil,
		wantErr: true,
	},
}
for _, tC := range tests {
	tt := tC
	t.Run(tt.name, func(t *testing.T) {
		t.Parallel()
		req, url := NewTestGock()
		defer gock.Remove(req.Mock)
		req.Get("v1/Finances/institutions").
			HeaderPresent("Authorization").
			Reply(200).
			JSON(expectedResp)
		c := coreapi.NewClient(&config.CoreAPI{
			BaseURL: url,
		})
		got, err := c.Get(tt.args.ctx, tt.args.path)
		if (err != nil) != tt.wantErr {
			t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
			return
		}
		if !reflect.DeepEqual(bytes.TrimRight(got, "\n"), bytes.TrimRight(tt.want, "\n")) {
			t.Errorf("Get() got = %v, want %v", got, tt.want)
		}
	})
}

}`

@steffakasid
Copy link

steffakasid commented Jun 13, 2024

Doesn't work for me...

I just disabled the t.Parrallel() for the few cases I had...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants