Skip to content

Commit f554d6b

Browse files
authored
[test-improver] Improve tests for mcp package (#2567)
## File Analyzed - **Test File**: `internal/mcp/connection_stderr_test.go` - **Package**: `internal/mcp` - **Lines of Code**: 38 → 79 (documentation-only test replaced with real tests) ## Improvements Made ### 1. Replaced Documentation-Only Test with Real Tests The original file contained a single test `TestConnection_MultipleServersStderrLogging` that only called `t.Log(...)` — no assertions, no real verification of any behavior. It was purely a design note disguised as a test. The file is now replaced with four substantive tests targeting previously untested code paths. ### 2. Increased Coverage - ✅ **`TestConnection_SendRequest`**: Exercises the `SendRequest` wrapper method which was **never tested** anywhere in the test suite. Verifies it delegates correctly to `SendRequestWithServerID` via a plain JSON-RPC HTTP test server. - ✅ **`TestConnection_SendRequest_UnsupportedMethod`**: Verifies `SendRequest` surfaces errors from the transport layer (unsupported method path). - ✅ **`TestConnection_Close_NilSession`**: Verifies `Close()` returns nil without panicking when there is no active SDK session. - ✅ **`TestConnection_Close_CancelsContext`**: Verifies `Close()` cancels the underlying context, making it unusable for further use. **Previously covered**: `SendRequest` — 0 test cases **Now covered**: `SendRequest` — 2 test cases; `Close` — 2 explicit test cases ### 3. Cleaner & More Stable Tests - ✅ Uses existing `newPlainJSONTestServer` and `newTestConnection` helpers (no duplication) - ✅ Uses testify `require`/`assert` throughout (consistent with the rest of the package) - ✅ Proper resource cleanup with `defer conn.Close()` and `defer srv.Close()` - ✅ Descriptive test names using `TestFunctionName_Scenario` format ## Why These Changes? `connection_stderr_test.go` was the only non-benchmark test file in the entire codebase that imported nothing but `"testing"` and contained no assertions. Meanwhile, `Connection.SendRequest` — a public method on a core type — had zero test coverage despite being straightforward to test. These changes convert a no-op documentation comment into four working tests that catch real regressions. --- *Generated by Test Improver Workflow* *Focuses on better patterns, increased coverage, and more stable tests* > Generated by [Test Improver](https://github.com/github/gh-aw-mcpg/actions/runs/23581468264) · [◷](https://github.com/search?q=repo%3Agithub%2Fgh-aw-mcpg+%22gh-aw-workflow-id%3A+test-improver%22&type=pullrequests) <!-- gh-aw-agentic-workflow: Test Improver, engine: copilot, model: auto, id: 23581468264, workflow_id: test-improver, run: https://github.com/github/gh-aw-mcpg/actions/runs/23581468264 --> <!-- gh-aw-workflow-id: test-improver -->
2 parents 3dea6d8 + effd62a commit f554d6b

1 file changed

Lines changed: 72 additions & 31 deletions

File tree

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,79 @@
11
package mcp
22

33
import (
4+
"context"
5+
"encoding/json"
6+
"net/http"
47
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
511
)
612

7-
// TestConnection_MultipleServersStderrLogging documents the expected behavior for serverID in stderr logs
8-
func TestConnection_MultipleServersStderrLogging(t *testing.T) {
9-
// This test documents the expected behavior of stderr logging with serverID.
10-
//
11-
// Before this change, stderr from parallel backend servers was interleaved without attribution:
12-
//
13-
// mcp:connection [stderr] ✗ failed to run status command: exit status 1 +357ms
14-
// mcp:connection [stderr] Output: unknown command "aw" for "gh" +779µs
15-
// mcp:connection [stderr] Did you mean this? +697µs
16-
// mcp:connection [stderr] co +982µs
17-
// mcp:connection [stderr] pr +1ms
18-
//
19-
// After this change, stderr logs include the serverID for clear attribution:
20-
//
21-
// mcp:connection [server1 stderr] ✗ failed to run status command: exit status 1 +357ms
22-
// mcp:connection [server2 stderr] Output: unknown command "aw" for "gh" +779µs
23-
// mcp:connection [server1 stderr] Did you mean this? +697µs
24-
// mcp:connection [server2 stderr] co +982µs
25-
// mcp:connection [server1 stderr] pr +1ms
26-
//
27-
// This makes it clear which server each log line is from when multiple backend servers
28-
// run in parallel.
29-
//
30-
// The serverID is passed through:
31-
// 1. Launcher has serverID when calling NewConnection or NewHTTPConnection
32-
// 2. Connection struct stores serverID field
33-
// 3. Stderr streaming goroutine includes serverID: logConn.Printf("[%s stderr] %s", serverID, line)
34-
35-
t.Log("This test documents the expected behavior for multiple servers")
36-
t.Log("With the serverID in stderr logs, parallel server logs are now distinguishable")
37-
t.Log("See internal/mcp/connection.go:202 for the implementation")
13+
// TestConnection_SendRequest verifies that SendRequest delegates to SendRequestWithServerID
14+
// using "unknown" as the serverID and context.Background() as the context.
15+
// This tests the simplified API surface used by callers that don't need to specify a serverID.
16+
func TestConnection_SendRequest(t *testing.T) {
17+
var receivedMethod string
18+
19+
srv := newPlainJSONTestServer(t, func(w http.ResponseWriter, r *http.Request, method string, _ []byte) {
20+
receivedMethod = method
21+
22+
w.Header().Set("Content-Type", "application/json")
23+
json.NewEncoder(w).Encode(map[string]interface{}{
24+
"jsonrpc": "2.0",
25+
"id": 1,
26+
"result": map[string]interface{}{
27+
"tools": []interface{}{},
28+
},
29+
})
30+
})
31+
defer srv.Close()
32+
33+
conn, err := NewHTTPConnection(context.Background(), "test-server", srv.URL, map[string]string{
34+
"Authorization": "test-token",
35+
})
36+
require.NoError(t, err)
37+
defer conn.Close()
38+
39+
resp, err := conn.SendRequest("tools/list", nil)
40+
require.NoError(t, err)
41+
assert.NotNil(t, resp)
42+
assert.Equal(t, "2.0", resp.JSONRPC)
43+
assert.Equal(t, "tools/list", receivedMethod)
44+
}
45+
46+
// TestConnection_SendRequest_UnsupportedMethod verifies that SendRequest surfaces errors
47+
// from the underlying transport (e.g., unsupported method on a nil-session stdio connection).
48+
func TestConnection_SendRequest_UnsupportedMethod(t *testing.T) {
49+
conn := newTestConnection(t)
50+
51+
result, err := conn.SendRequest("unsupported/method", nil)
52+
require.Error(t, err)
53+
assert.Nil(t, result)
54+
assert.Contains(t, err.Error(), "unsupported method")
55+
}
56+
57+
// TestConnection_Close_NilSession verifies that Close does not panic and returns nil
58+
// when the connection has no active SDK session (e.g., plain JSON-RPC or test connections).
59+
func TestConnection_Close_NilSession(t *testing.T) {
60+
conn := newTestConnection(t)
61+
assert.Nil(t, conn.session, "test connection should have no session")
62+
err := conn.Close()
63+
assert.NoError(t, err)
64+
}
65+
66+
// TestConnection_Close_CancelsContext verifies that Close cancels the connection context,
67+
// making it unusable for further requests.
68+
func TestConnection_Close_CancelsContext(t *testing.T) {
69+
ctx, cancel := context.WithCancel(context.Background())
70+
conn := &Connection{
71+
ctx: ctx,
72+
cancel: cancel,
73+
}
74+
require.NoError(t, ctx.Err(), "context should be valid before Close")
75+
76+
err := conn.Close()
77+
assert.NoError(t, err)
78+
assert.ErrorIs(t, ctx.Err(), context.Canceled, "context should be cancelled after Close")
3879
}

0 commit comments

Comments
 (0)