From 30db4b8631e9e23ee1c85fe5910bc106dcc091a8 Mon Sep 17 00:00:00 2001 From: Taichi Sasaki Date: Tue, 23 Sep 2025 09:14:46 +0900 Subject: [PATCH 1/2] Add test for generateClient() in testing/codegen --- testing/codegen/clients_test.go | 46 +++++++++++++++ testing/codegen/testdata/code.go | 96 ++++++++++++++++++++++++++++++++ testing/codegen/testdata/dsls.go | 27 +++++++++ 3 files changed, 169 insertions(+) create mode 100644 testing/codegen/clients_test.go diff --git a/testing/codegen/clients_test.go b/testing/codegen/clients_test.go new file mode 100644 index 00000000..851ecff3 --- /dev/null +++ b/testing/codegen/clients_test.go @@ -0,0 +1,46 @@ +package codegen + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "goa.design/goa/v3/codegen/service" + httpcodegen "goa.design/goa/v3/http/codegen" + "goa.design/plugins/v3/testing/codegen/testdata" +) + +func TestGenerateClient(t *testing.T) { + cases := map[string]struct { + DSL func() + Code map[string][]string + Path string + }{ + "with-result": { + DSL: testdata.WithResultDSL, + Code: map[string][]string{ + "client-methods": {testdata.WithResultCode}, + }, + Path: "gen/with_result_service/with_result_servicetest/client.go", + }, + "without-result": { + DSL: testdata.WithoutResultDSL, + Code: map[string][]string{ + "client-methods": {testdata.WithoutResultCode}, + }, + Path: "gen/without_result_service/without_result_servicetest/client.go", + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + root := httpcodegen.RunHTTPDSL(t, c.DSL) + services := service.NewServicesData(root) + svc := root.Services[0] + svcData := services.Get(svc.Name) + f := generateClient("", svcData, root, svc) + assert.Equal(t, c.Path, f.Path) + for sec, secCode := range c.Code { + testCode(t, f, sec, secCode) + } + }) + } +} diff --git a/testing/codegen/testdata/code.go b/testing/codegen/testdata/code.go index bc9707d1..4d89a7d1 100644 --- a/testing/codegen/testdata/code.go +++ b/testing/codegen/testdata/code.go @@ -1,5 +1,101 @@ package testdata +var WithResultCode = `// WithResultMethod calls the WithResultMethod method using the configured +// transport. +func (c *Client) WithResultMethod(ctx context.Context) (*withresultservice.WithResultMethodResult, error) { + // Determine which transport to use + transport := c.transport + if transport == AutoTransport { + // Use the first available transport + if c.httpClient != nil { + transport = HTTPTransport + } else if c.grpcClient != nil { + transport = GRPCTransport + } else if c.jsonrpcClient != nil { + transport = JSONRPCTransport + } + } + + switch transport { + case HTTPTransport: + if c.httpClient == nil { + return nil, fmt.Errorf("HTTP transport not configured") + } + endpoint := c.httpClient.WithResultMethod() + res, err := endpoint(ctx) + if err != nil { + return nil, err + } + return res.(*withresultservice.WithResultMethodResult), nil + case GRPCTransport: + if c.grpcClient == nil { + return nil, fmt.Errorf("gRPC transport not configured") + } + endpoint := c.grpcClient.WithResultMethod() + res, err := endpoint(ctx) + if err != nil { + return nil, err + } + return res.(*withresultservice.WithResultMethodResult), nil + case JSONRPCTransport: + if c.jsonrpcClient == nil { + return nil, fmt.Errorf("JSON-RPC transport not configured") + } + endpoint := c.jsonrpcClient.WithResultMethod() + res, err := endpoint(ctx) + if err != nil { + return nil, err + } + return res.(*withresultservice.WithResultMethodResult), nil + + default: + return nil, fmt.Errorf("no transport available for WithResultMethod") + } +} +` + +var WithoutResultCode = `// WithoutResultMethod calls the WithoutResultMethod method using the +// configured transport. +func (c *Client) WithoutResultMethod(ctx context.Context) error { + // Determine which transport to use + transport := c.transport + if transport == AutoTransport { + // Use the first available transport + if c.httpClient != nil { + transport = HTTPTransport + } else if c.grpcClient != nil { + transport = GRPCTransport + } else if c.jsonrpcClient != nil { + transport = JSONRPCTransport + } + } + + switch transport { + case HTTPTransport: + if c.httpClient == nil { + return fmt.Errorf("HTTP transport not configured") + } + endpoint := c.httpClient.WithoutResultMethod() + return endpoint(ctx) + case GRPCTransport: + if c.grpcClient == nil { + return fmt.Errorf("gRPC transport not configured") + } + endpoint := c.grpcClient.WithoutResultMethod() + return endpoint(ctx) + case JSONRPCTransport: + if c.jsonrpcClient == nil { + return fmt.Errorf("JSON-RPC transport not configured") + } + endpoint := c.jsonrpcClient.WithoutResultMethod() + return endpoint(ctx) + + default: + return fmt.Errorf("no transport available for WithoutResultMethod") + } +} +` + var WithStreamCode = `// setupHTTP initializes the HTTP test server and client. func (h *Harness) setupHTTP() { // Create endpoints diff --git a/testing/codegen/testdata/dsls.go b/testing/codegen/testdata/dsls.go index fb41be80..a2e58f45 100644 --- a/testing/codegen/testdata/dsls.go +++ b/testing/codegen/testdata/dsls.go @@ -4,6 +4,33 @@ import ( . "goa.design/goa/v3/dsl" ) +var WithResultDSL = func() { + Service("WithResultService", func() { + Method("WithResultMethod", func() { + Result(func() { + Field(1, "Attribute", String) + }) + HTTP(func() { + GET("/") + }) + GRPC(func() {}) + JSONRPC(func() {}) + }) + }) +} + +var WithoutResultDSL = func() { + Service("WithoutResultService", func() { + Method("WithoutResultMethod", func() { + HTTP(func() { + GET("/") + }) + GRPC(func() {}) + JSONRPC(func() {}) + }) + }) +} + var WithStreamDSL = func() { Service("WithStreamService", func() { Method("WithStreamMethod", func() { From 3c19e63afcfb16d0a5c75b4a81bd08b8a9409184 Mon Sep 17 00:00:00 2001 From: Taichi Sasaki Date: Tue, 23 Sep 2025 09:28:14 +0900 Subject: [PATCH 2/2] Fix Client methods without result generated by testing/codegen --- testing/codegen/templates/client_methods.go.tpl | 11 +++++++---- testing/codegen/testdata/code.go | 9 ++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/testing/codegen/templates/client_methods.go.tpl b/testing/codegen/templates/client_methods.go.tpl index 7437b46f..8946a739 100644 --- a/testing/codegen/templates/client_methods.go.tpl +++ b/testing/codegen/templates/client_methods.go.tpl @@ -64,7 +64,8 @@ func (c *Client) {{ $method.VarName }}(ctx context.Context{{- if $method.Payload } return res.(*{{ $.PkgName }}.{{ $method.Result }}), nil {{- else }} - return endpoint(ctx{{- if $method.PayloadRef }}, p{{ end }}) + _, err := endpoint(ctx, {{- if $method.PayloadRef }}p{{ else }}nil{{ end }}) + return err {{- end }} {{- end }} {{- end }} @@ -89,7 +90,8 @@ func (c *Client) {{ $method.VarName }}(ctx context.Context{{- if $method.Payload } return res.(*{{ $.PkgName }}.{{ $method.Result }}), nil {{- else }} - return endpoint(ctx{{- if $method.PayloadRef }}, p{{ end }}) + _, err := endpoint(ctx, {{- if $method.PayloadRef }}p{{ else }}nil{{ end }}) + return err {{- end }} {{- end }} {{- end }} @@ -129,7 +131,8 @@ func (c *Client) {{ $method.VarName }}(ctx context.Context{{- if $method.Payload } return res.(*{{ $.PkgName }}.{{ $method.Result }}), nil {{- else }} - return endpoint(ctx{{- if $method.PayloadRef }}, p{{ end }}) + _, err := endpoint(ctx, {{- if $method.PayloadRef }}p{{ else }}nil{{ end }}) + return err {{- end }} {{- end }} {{- end }} @@ -139,4 +142,4 @@ func (c *Client) {{ $method.VarName }}(ctx context.Context{{- if $method.Payload } } -{{- end }} \ No newline at end of file +{{- end }} diff --git a/testing/codegen/testdata/code.go b/testing/codegen/testdata/code.go index 4d89a7d1..b13300ef 100644 --- a/testing/codegen/testdata/code.go +++ b/testing/codegen/testdata/code.go @@ -76,19 +76,22 @@ func (c *Client) WithoutResultMethod(ctx context.Context) error { return fmt.Errorf("HTTP transport not configured") } endpoint := c.httpClient.WithoutResultMethod() - return endpoint(ctx) + _, err := endpoint(ctx, nil) + return err case GRPCTransport: if c.grpcClient == nil { return fmt.Errorf("gRPC transport not configured") } endpoint := c.grpcClient.WithoutResultMethod() - return endpoint(ctx) + _, err := endpoint(ctx, nil) + return err case JSONRPCTransport: if c.jsonrpcClient == nil { return fmt.Errorf("JSON-RPC transport not configured") } endpoint := c.jsonrpcClient.WithoutResultMethod() - return endpoint(ctx) + _, err := endpoint(ctx, nil) + return err default: return fmt.Errorf("no transport available for WithoutResultMethod")