From 50c1033ad1b33817b3e3907b5bc84f124c01aabf Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Fri, 13 Sep 2024 21:27:13 +0100 Subject: [PATCH] Use the mocks for tests and benchmarks. --- main.go | 5 ++ mock_server.go | 67 +++++++++++++++++ query_bench_test.go | 21 +++++- query_test.go | 175 +++++--------------------------------------- suite_test.go | 16 +++- 5 files changed, 126 insertions(+), 158 deletions(-) create mode 100644 mock_server.go diff --git a/main.go b/main.go index 3015951..07e853f 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package gql import ( + "net/http" "time" "github.com/gookit/goutil/envutil" @@ -38,3 +39,7 @@ func (b *BaseClient) SetOutput(responseType string) { // TODO: implement b.responseType = responseType } + +func (b *BaseClient) SetHTTPClient(client *http.Client) { + b.client = client +} diff --git a/mock_server.go b/mock_server.go new file mode 100644 index 0000000..1352697 --- /dev/null +++ b/mock_server.go @@ -0,0 +1,67 @@ +// mock_server.go +package gql + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "net/http/httptest" + "strings" + + "golang.org/x/net/http2" +) + +func StartMockServer() *httptest.Server { + // Create your handler + handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Your existing handler code + bodyBytes, err := ioutil.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + var req struct { + Query string `json:"query"` + Variables map[string]interface{} `json:"variables"` + } + err = json.Unmarshal(bodyBytes, &req) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + // Simple validation to check for unbalanced braces as a syntax error + if !strings.HasPrefix(strings.TrimSpace(req.Query), "query") || !strings.HasSuffix(strings.TrimSpace(req.Query), "}") { + resp := []byte(`{"errors":[{"message":"Syntax Error: Invalid query"}]}`) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusBadRequest) + w.Write(resp) + return + } + + var resp []byte + if strings.Contains(req.Query, "viewer") { + resp = []byte(`{"data":{"viewer":{"login":"mockuser"}}}`) + } else if strings.Contains(req.Query, "dragons") { + resp = []byte(`{"data":{"dragons":[{"name":"Mock Dragon 1"},{"name":"Mock Dragon 2"}]}}`) + } else { + resp = []byte(`{"errors":[{"message":"Unknown query"}]}`) + w.WriteHeader(http.StatusBadRequest) + } + + w.Header().Set("Content-Type", "application/json") + w.Write(resp) + }) + + // Create an unstarted server + server := httptest.NewUnstartedServer(handler) + + // Configure the server to support HTTP/2 + http2.ConfigureServer(server.Config, &http2.Server{}) + server.TLS = server.Config.TLSConfig + + // Start the server with TLS + server.StartTLS() + return server +} diff --git a/query_bench_test.go b/query_bench_test.go index 018845f..f99454a 100644 --- a/query_bench_test.go +++ b/query_bench_test.go @@ -36,10 +36,15 @@ func Benchmark_convertToJson(bn *testing.B) { b.convertToJSON(query) } } - func Benchmark_Query(bn *testing.B) { + mockServer := StartMockServer() + bn.Cleanup(func() { + mockServer.Close() + }) + b := NewConnection() - query := `query { viewer { login } }` + b.SetEndpoint(mockServer.URL) + query := "query { viewer { login } }" variables := map[string]interface{}{ "var1": "value1", } @@ -54,7 +59,13 @@ func Benchmark_Query(bn *testing.B) { } func Benchmark_QueryNoCacheNoRetry(bn *testing.B) { + mockServer := StartMockServer() + bn.Cleanup(func() { + mockServer.Close() + }) + b := NewConnection() + b.SetEndpoint(mockServer.URL) query := `query { viewer { login } }` variables := map[string]interface{}{ "var1": "value1", @@ -69,7 +80,13 @@ func Benchmark_QueryNoCacheNoRetry(bn *testing.B) { } func Benchmark_QueryWithEmptyVariables(bn *testing.B) { + mockServer := StartMockServer() + bn.Cleanup(func() { + mockServer.Close() + }) + b := NewConnection() + b.SetEndpoint(mockServer.URL) query := `query { viewer { login } }` headers := map[string]interface{}{ "Authorization": "Bearer token", diff --git a/query_test.go b/query_test.go index 1790d79..c39a7fa 100644 --- a/query_test.go +++ b/query_test.go @@ -115,182 +115,48 @@ func (suite *Tests) TestBaseClient_Query() { args args wantReturned_value any name string - graphQLServer string wantType string wantErr bool }{ { - name: "TestBaseClient_Query_spacex_working", - graphQLServer: "https://spacex-production.up.railway.app/", + name: "TestBaseClient_Query_viewer", args: args{ - query: `query Dragons { - dragons { - name - } - }`, + query: "query { viewer { login } }", variables: nil, headers: map[string]interface{}{ - "x-apollo-operation-name": "Dragons/github.com/lukaszraczylo/go-simple-graphql", + "x-apollo-operation-name": "ViewerQuery", "content-type": "application/json", }, }, - wantReturned_value: string(`{"dragons":[{"name":"Dragon 1"},{"name":"Dragon 2"}]}`), + wantReturned_value: `{"viewer":{"login":"mockuser"}}`, // Adjusted expected value wantErr: false, }, { - name: "TestBaseClient_Query_spacex_invalid_query", - graphQLServer: "https://spacex-production.up.railway.app/", + name: "TestBaseClient_Query_dragons", args: args{ query: `query Dragons { - dragons { - name - } - `, + dragons { + name + } + }`, variables: nil, headers: map[string]interface{}{ - "x-apollo-operation-name": "Dragons/github.com/lukaszraczylo/go-simple-graphql", + "x-apollo-operation-name": "DragonsQuery", "content-type": "application/json", }, }, - wantReturned_value: nil, - wantErr: true, - }, - { - name: "TestBaseClient_Query_tgbotapp_working", - graphQLServer: "https://telegram-bot.app/v1/graphql", - args: args{ - query: `query { - __type(name: "Query") { - name - } - }`, - }, - wantReturned_value: string(`{"__type":null}`), + wantReturned_value: `{"dragons":[{"name":"Mock Dragon 1"},{"name":"Mock Dragon 2"}]}`, // Adjusted expected value wantErr: false, }, + { - name: "TestBaseClient_Query_tgbotapp_invalid_query", - graphQLServer: "https://telegram-bot.app/v1/graphql", + name: "TestBaseClient_Query_invalid_query", args: args{ - query: `query { - __type(name: "Query") { - name - } - `, - }, - wantReturned_value: nil, - wantErr: true, - }, - { - name: "TestBaseClient_Query_tgbotapp_invalid_wrong_field", - graphQLServer: "https://telegram-bot.app/v1/graphql", - args: args{ - query: `query { - __type(name: "Query") { - name2 - } - }`, - }, - wantReturned_value: nil, - wantErr: true, - }, - { - name: "TestBaseClient_Query_tgbotapp_wrong_url", - graphQLServer: "https://telegram-bot.app/v0/graphql", - args: args{ - query: `query { - __type(name: "Query") { - name - } - }`, - }, - wantReturned_value: nil, - wantErr: true, - }, - { - name: "TestBaseClient_Query_tgbotapp_valid_query_mapstring", - graphQLServer: "https://telegram-bot.app/v1/graphql", - wantType: "mapstring", - args: args{ - query: `query { - __type(name: "Query") { - name - } - }`, - }, - wantReturned_value: map[string]interface{}{"__type": nil}, - wantErr: false, - }, - { - name: "TestBaseClient_Query_tgbotapp_valid_query_byte", - graphQLServer: "https://telegram-bot.app/v1/graphql", - wantType: "byte", - args: args{ - query: `query { - __type(name: "Query") { - name - } - }`, - }, - wantReturned_value: []byte(`{"__type":null}`), - wantErr: false, - }, - { - name: "TestBaseClient_Query_tgbotapp_valid_query_string", - graphQLServer: "https://telegram-bot.app/v1/graphql", - wantType: "string", - args: args{ - query: `query { - __type(name: "Query") { - name - } - }`, - }, - wantReturned_value: string(`{"__type":null}`), - wantErr: false, - }, - { - name: "TestBaseClient_Query_tgbotapp_valid_query_invalid_type", - graphQLServer: "https://telegram-bot.app/v1/graphql", - wantType: "potato", - args: args{ - query: `query { - __type(name: "Query") { - name - } - }`, - }, - wantReturned_value: nil, - wantErr: true, - }, - { - name: "TestBaseClient_Query_tgbotapp_valid_query_cache", - graphQLServer: "https://telegram-bot.app/v1/graphql", - args: args{ - query: `query { - __type(name: "Query") { - name - } - }`, - variables: map[string]interface{}{ - "gqlcache": true, - }, - }, - wantReturned_value: string(`{"__type":null}`), - wantErr: false, - }, - { - name: "TestBaseClient_Query_tgbotapp_valid_query_with_retry", - graphQLServer: "https://telegram-bot.app/v0/graphql", - wantType: "byte", - args: args{ - query: `query { - __type(name: "Query") { - name - } - }`, - variables: map[string]interface{}{ - "gqlretries": true, + query: "query { potato { login } ", + variables: nil, + headers: map[string]interface{}{ + "x-apollo-operation-name": "InvalidQuery", + "content-type": "application/json", }, }, wantReturned_value: nil, @@ -300,9 +166,8 @@ func (suite *Tests) TestBaseClient_Query() { for _, tt := range tests { suite.T().Run(tt.name, func(t *testing.T) { b := NewConnection() - if tt.graphQLServer != "" { - b.SetEndpoint(tt.graphQLServer) - } + b.SetEndpoint(mockServer.URL) + b.SetHTTPClient(mockServer.Client()) if tt.wantType != "" { b.SetOutput(tt.wantType) } diff --git a/suite_test.go b/suite_test.go index 9d77708..623132e 100644 --- a/suite_test.go +++ b/suite_test.go @@ -1,6 +1,7 @@ package gql import ( + "net/http/httptest" "testing" assertions "github.com/stretchr/testify/assert" @@ -12,9 +13,22 @@ type Tests struct { } var ( - assert *assertions.Assertions + assert *assertions.Assertions + mockServer *httptest.Server ) +func (suite *Tests) SetupSuite() { + // Start mock GraphQL server + mockServer = StartMockServer() +} + +func (suite *Tests) TearDownSuite() { + // Close the mock server + if mockServer != nil { + mockServer.Close() + } +} + func (suite *Tests) SetupTest() { assert = assertions.New(suite.T()) }