Repository: apache/incubator-seata-go

Issue:
Improve test coverage for pkg/integration/dubbo
- **Package**: `seata.apache.org/seata-go/pkg/integration/dubbo`
- **Current Coverage**: 17.9%
- **Target Coverage**: >= 70%
- **Description**: The package currently has low test coverage. We need to add more unit tests to improve code quality and maintainability.
- **Task**:
  1. Analyze the code in this package
  2. Identify code paths that are not covered by tests
  3. Write unit tests to cover those paths
  4. Ensure tests are comprehensive and meaningful

Discussion:
@everfid-ever: plz assign to me
@slievrly: @everfid-ever I have assigned it to you and look forward to your PR submission.

Solution patch:
diff --git a/makefile b/makefile
index 3649ac4..dcd971d 100644
--- a/makefile
+++ b/makefile
@@ -16,6 +16,8 @@
 #
 
 VERSION=$(shell tail -n 1 "./VERSION" 2> /dev/null)
+GIT_BRANCH=$(shell git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
+GIT_REVISION=$(shell git rev-parse HEAD 2>/dev/null || echo "unknown")
 
 GO_FLAGS := -ldflags "-X main.Branch=$(GIT_BRANCH) -X main.Revision=$(GIT_REVISION) -X main.Version=$(VERSION) -extldflags \"-static\" -s -w" -tags netgo
 GO = go



Test patch:
diff --git a/pkg/integration/dubbo/dubbo_transaction_filter_test.go b/pkg/integration/dubbo/dubbo_transaction_filter_test.go
index 3e084eb..c3cb995 100644
--- a/pkg/integration/dubbo/dubbo_transaction_filter_test.go
+++ b/pkg/integration/dubbo/dubbo_transaction_filter_test.go
@@ -19,11 +19,17 @@ package dubbo
 
 import (
 	"context"
+	"reflect"
+	"strings"
 	"testing"
 
+	"dubbo.apache.org/dubbo-go/v3/common"
 	"dubbo.apache.org/dubbo-go/v3/filter"
 	"dubbo.apache.org/dubbo-go/v3/protocol"
 	"github.com/stretchr/testify/assert"
+
+	"seata.apache.org/seata-go/pkg/constant"
+	"seata.apache.org/seata-go/pkg/tm"
 )
 
 // TestGetDubboTransactionFilter unit test for GetDubboTransactionFilter
@@ -33,11 +39,11 @@ func TestGetDubboTransactionFilter(t *testing.T) {
 		want filter.Filter
 	}{
 		{
-			name: "TestGetDubboTransactionFilter",
+			name: "first_call",
 			want: GetDubboTransactionFilter(),
 		},
 		{
-			name: "TestGetDubboTransactionFilter1",
+			name: "second_call_returns_same_instance",
 			want: GetDubboTransactionFilter(),
 		},
 	}
@@ -48,45 +54,411 @@ func TestGetDubboTransactionFilter(t *testing.T) {
 	}
 }
 
-// TestGetDubboTransactionFilter unit test for GetDubboTransactionFilter
+// TestDubboTransactionFilterOnResponse unit test for OnResponse
 func TestDubboTransactionFilterOnResponse(t *testing.T) {
-	type args struct {
+	tests := []struct {
+		name       string
 		ctx        context.Context
 		result     protocol.Result
 		invoker    protocol.Invoker
 		invocation protocol.Invocation
+		want       protocol.Result
+	}{
+		{
+			name:       "with_background_context",
+			ctx:        context.Background(),
+			result:     nil,
+			invoker:    nil,
+			invocation: nil,
+			want:       nil,
+		},
+		{
+			name:       "with_todo_context",
+			ctx:        context.TODO(),
+			result:     nil,
+			invoker:    nil,
+			invocation: nil,
+			want:       nil,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			du := &dubboTransactionFilter{}
+			got := du.OnResponse(tt.ctx, tt.result, tt.invoker, tt.invocation)
+			assert.Equal(t, tt.want, got)
+		})
+	}
+}
+
+type mockInvocation struct {
+	attachments map[string]interface{}
+}
+
+func newMockInvocation() *mockInvocation {
+	return &mockInvocation{
+		attachments: make(map[string]interface{}),
 	}
+}
+
+func (m *mockInvocation) MethodName() string                  { return "mockMethod" }
+func (m *mockInvocation) ParameterTypeNames() []string        { return nil }
+func (m *mockInvocation) ParameterTypes() []reflect.Type      { return nil }
+func (m *mockInvocation) ParameterValues() []reflect.Value    { return nil }
+func (m *mockInvocation) Arguments() []interface{}            { return nil }
+func (m *mockInvocation) Reply() interface{}                  { return nil }
+func (m *mockInvocation) Attachments() map[string]interface{} { return m.attachments }
+func (m *mockInvocation) Attributes() map[string]interface{}  { return nil }
+func (m *mockInvocation) AttributeByKey(string, interface{}) interface{} {
+	return nil
+}
+func (m *mockInvocation) SetAttachment(key string, value interface{}) {
+	m.attachments[key] = value
+}
+func (m *mockInvocation) GetAttachment(key string) (string, bool) {
+	if val, ok := m.attachments[key]; ok {
+		if str, ok := val.(string); ok {
+			return str, true
+		}
+	}
+	return "", false
+}
+func (m *mockInvocation) GetAttachmentWithDefaultValue(key, defaultValue string) string {
+	if val, ok := m.GetAttachment(key); ok {
+		return val
+	}
+	return defaultValue
+}
+func (m *mockInvocation) ServiceKey() string          { return "" }
+func (m *mockInvocation) Invoker() protocol.Invoker   { return nil }
+func (m *mockInvocation) SetInvoker(protocol.Invoker) {}
+func (m *mockInvocation) ActualMethodName() string    { return "mockMethod" }
+func (m *mockInvocation) IsGenericInvocation() bool   { return false }
+func (m *mockInvocation) GetAttachmentInterface(key string) interface{} {
+	return m.attachments[key]
+}
+func (m *mockInvocation) GetAttachmentAsContext() context.Context { return context.Background() }
+func (m *mockInvocation) SetAttribute(string, interface{})        {}
+func (m *mockInvocation) GetAttribute(string) (interface{}, bool) { return nil, false }
+func (m *mockInvocation) GetAttributeWithDefaultValue(string, interface{}) interface{} {
+	return nil
+}
+
+type mockInvoker struct {
+	invoked    bool
+	invokeFunc func(context.Context, protocol.Invocation) protocol.Result
+}
+
+func (m *mockInvoker) GetURL() *common.URL { return nil }
+func (m *mockInvoker) IsAvailable() bool   { return true }
+func (m *mockInvoker) Destroy()            {}
+func (m *mockInvoker) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result {
+	m.invoked = true
+	if m.invokeFunc != nil {
+		return m.invokeFunc(ctx, invocation)
+	}
+	return &mockResult{}
+}
+
+type mockResult struct {
+	err   error
+	value interface{}
+}
+
+func (m *mockResult) SetError(err error)                         { m.err = err }
+func (m *mockResult) Error() error                               { return m.err }
+func (m *mockResult) SetResult(value interface{})                { m.value = value }
+func (m *mockResult) Result() interface{}                        { return m.value }
+func (m *mockResult) SetAttachments(map[string]interface{})      {}
+func (m *mockResult) Attachments() map[string]interface{}        { return nil }
+func (m *mockResult) AddAttachment(string, interface{})          {}
+func (m *mockResult) Attachment(string, interface{}) interface{} { return nil }
+
+// TestInvoke tests various scenarios of the Invoke method
+func TestInvoke(t *testing.T) {
 	tests := []struct {
-		name string
-		args args
-		want protocol.Result
+		name               string
+		setupCtx           func() context.Context
+		setupInvocation    func() *mockInvocation
+		setupInvoker       func() *mockInvoker
+		wantInvoked        bool
+		validateResult     func(*testing.T, protocol.Result)
+		validateContext    func(*testing.T, context.Context)
+		validateInvocation func(*testing.T, *mockInvocation)
 	}{
 		{
-			name: "Test_dubboTransactionFilter_OnResponse",
-			args: args{
-				ctx:        context.Background(),
-				result:     nil,
-				invoker:    nil,
-				invocation: nil,
+			name: "with_xid_in_context",
+			setupCtx: func() context.Context {
+				ctx := tm.InitSeataContext(context.Background())
+				tm.SetXID(ctx, "context-xid-123")
+				return ctx
+			},
+			setupInvocation: func() *mockInvocation {
+				return newMockInvocation()
+			},
+			setupInvoker: func() *mockInvoker {
+				return &mockInvoker{}
+			},
+			wantInvoked: true,
+			validateResult: func(t *testing.T, result protocol.Result) {
+				assert.NotNil(t, result)
+			},
+			validateInvocation: func(t *testing.T, inv *mockInvocation) {
+				seataXid, ok := inv.GetAttachment(constant.SeataXidKey)
+				assert.True(t, ok)
+				assert.Equal(t, "context-xid-123", seataXid)
+
+				txXid, ok := inv.GetAttachment(constant.XidKey)
+				assert.True(t, ok)
+				assert.Equal(t, "context-xid-123", txXid)
 			},
-			want: nil,
 		},
 		{
-			name: "Test_dubboTransactionFilter_OnResponse1",
-			args: args{
-				ctx:        context.TODO(),
-				result:     nil,
-				invoker:    nil,
-				invocation: nil,
+			name: "with_rpc_xid_only",
+			setupCtx: func() context.Context {
+				return context.Background()
+			},
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(constant.SeataXidKey, "rpc-xid-456")
+				return inv
+			},
+			setupInvoker: func() *mockInvoker {
+				return &mockInvoker{
+					invokeFunc: func(ctx context.Context, inv protocol.Invocation) protocol.Result {
+						// Verify XID was set in context from RPC attachment
+						xid := tm.GetXID(ctx)
+						if xid != "rpc-xid-456" {
+							return &mockResult{err: assert.AnError}
+						}
+						return &mockResult{}
+					},
+				}
+			},
+			wantInvoked: true,
+			validateResult: func(t *testing.T, result protocol.Result) {
+				assert.NotNil(t, result)
+				assert.NoError(t, result.Error())
+			},
+		},
+		{
+			name: "no_xid",
+			setupCtx: func() context.Context {
+				return context.Background()
+			},
+			setupInvocation: func() *mockInvocation {
+				return newMockInvocation()
+			},
+			setupInvoker: func() *mockInvoker {
+				return &mockInvoker{}
+			},
+			wantInvoked: true,
+			validateResult: func(t *testing.T, result protocol.Result) {
+				assert.NotNil(t, result)
 			},
-			want: nil,
 		},
 	}
+
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			du := &dubboTransactionFilter{}
-			got := du.OnResponse(tt.args.ctx, tt.args.result, tt.args.invoker, tt.args.invocation)
-			assert.Equal(t, got, tt.want)
+			filter := &dubboTransactionFilter{}
+			ctx := tt.setupCtx()
+			invocation := tt.setupInvocation()
+			invoker := tt.setupInvoker()
+
+			result := filter.Invoke(ctx, invoker, invocation)
+
+			assert.Equal(t, tt.wantInvoked, invoker.invoked)
+
+			if tt.validateResult != nil {
+				tt.validateResult(t, result)
+			}
+
+			if tt.validateContext != nil {
+				tt.validateContext(t, ctx)
+			}
+
+			if tt.validateInvocation != nil {
+				tt.validateInvocation(t, invocation)
+			}
 		})
 	}
 }
+
+// TestGetRpcXid tests getRpcXid with various XID formats
+func TestGetRpcXid(t *testing.T) {
+	tests := []struct {
+		name               string
+		setupInvocation    func() *mockInvocation
+		expectedXid        string
+		expectedPrecedence string
+	}{
+		{
+			name: "dubbo_go_xid",
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(constant.SeataXidKey, "dubbo-go-xid")
+				return inv
+			},
+			expectedXid: "dubbo-go-xid",
+		},
+		{
+			name: "dubbo_go_xid_lowercase",
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(strings.ToLower(constant.SeataXidKey), "dubbo-go-lower-xid")
+				return inv
+			},
+			expectedXid: "dubbo-go-lower-xid",
+		},
+		{
+			name: "dubbo_java_xid",
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(constant.XidKey, "dubbo-java-xid")
+				return inv
+			},
+			expectedXid: "dubbo-java-xid",
+		},
+		{
+			name: "dubbo_java_xid_lowercase",
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(strings.ToLower(constant.XidKey), "dubbo-java-lower-xid")
+				return inv
+			},
+			expectedXid: "dubbo-java-lower-xid",
+		},
+		{
+			name: "dubbo_go_takes_precedence",
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(constant.SeataXidKey, "dubbo-go-xid")
+				inv.SetAttachment(constant.XidKey, "dubbo-java-xid")
+				return inv
+			},
+			expectedXid:        "dubbo-go-xid",
+			expectedPrecedence: "dubbo-go XID should take precedence",
+		},
+		{
+			name: "empty_xid",
+			setupInvocation: func() *mockInvocation {
+				return newMockInvocation()
+			},
+			expectedXid: "",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			filter := &dubboTransactionFilter{}
+			invocation := tt.setupInvocation()
+
+			xid := filter.getRpcXid(invocation)
+
+			if tt.expectedPrecedence != "" {
+				assert.Equal(t, tt.expectedXid, xid, tt.expectedPrecedence)
+			} else {
+				assert.Equal(t, tt.expectedXid, xid)
+			}
+		})
+	}
+}
+
+// TestGetDubboGoRpcXid tests getDubboGoRpcXid method
+func TestGetDubboGoRpcXid(t *testing.T) {
+	tests := []struct {
+		name            string
+		setupInvocation func() *mockInvocation
+		expectedXid     string
+	}{
+		{
+			name: "with_seata_xid",
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(constant.SeataXidKey, "go-xid-1")
+				return inv
+			},
+			expectedXid: "go-xid-1",
+		},
+		{
+			name: "with_lowercase_seata_xid",
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(strings.ToLower(constant.SeataXidKey), "go-xid-lower")
+				return inv
+			},
+			expectedXid: "go-xid-lower",
+		},
+		{
+			name: "empty",
+			setupInvocation: func() *mockInvocation {
+				return newMockInvocation()
+			},
+			expectedXid: "",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			filter := &dubboTransactionFilter{}
+			invocation := tt.setupInvocation()
+
+			xid := filter.getDubboGoRpcXid(invocation)
+
+			assert.Equal(t, tt.expectedXid, xid)
+		})
+	}
+}
+
+// TestGetDubboJavaRpcXid tests getDubboJavaRpcXid method
+func TestGetDubboJavaRpcXid(t *testing.T) {
+	tests := []struct {
+		name            string
+		setupInvocation func() *mockInvocation
+		expectedXid     string
+	}{
+		{
+			name: "with_xid_key",
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(constant.XidKey, "java-xid-1")
+				return inv
+			},
+			expectedXid: "java-xid-1",
+		},
+		{
+			name: "with_lowercase_xid_key",
+			setupInvocation: func() *mockInvocation {
+				inv := newMockInvocation()
+				inv.SetAttachment(strings.ToLower(constant.XidKey), "java-xid-lower")
+				return inv
+			},
+			expectedXid: "java-xid-lower",
+		},
+		{
+			name: "empty",
+			setupInvocation: func() *mockInvocation {
+				return newMockInvocation()
+			},
+			expectedXid: "",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			filter := &dubboTransactionFilter{}
+			invocation := tt.setupInvocation()
+
+			xid := filter.getDubboJavaRpcXid(invocation)
+
+			assert.Equal(t, tt.expectedXid, xid)
+		})
+	}
+}
+
+// TestInitSeataDubbo tests InitSeataDubbo function
+func TestInitSeataDubbo(t *testing.T) {
+	assert.NotPanics(t, func() {
+		InitSeataDubbo()
+	})
+}
diff --git a/pkg/remoting/mock/mock_getty_session_test.go b/pkg/remoting/mock/mock_getty_session_test.go
new file mode 100644
index 0000000..b00e656
--- /dev/null
+++ b/pkg/remoting/mock/mock_getty_session_test.go
@@ -0,0 +1,722 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mock
+
+import (
+	"errors"
+	"net"
+	"testing"
+	"time"
+
+	getty "github.com/apache/dubbo-getty"
+	"github.com/golang/mock/gomock"
+	"github.com/stretchr/testify/assert"
+)
+
+// mockConn is a mock implementation of net.Conn for testing
+type mockConn struct {
+	net.Conn
+}
+
+func (m *mockConn) Read(b []byte) (n int, err error)   { return 0, nil }
+func (m *mockConn) Write(b []byte) (n int, err error)  { return len(b), nil }
+func (m *mockConn) Close() error                       { return nil }
+func (m *mockConn) LocalAddr() net.Addr                { return &net.TCPAddr{} }
+func (m *mockConn) RemoteAddr() net.Addr               { return &net.TCPAddr{} }
+func (m *mockConn) SetDeadline(t time.Time) error      { return nil }
+func (m *mockConn) SetReadDeadline(t time.Time) error  { return nil }
+func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil }
+
+func TestNewMockTestSession(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	assert.NotNil(t, mock, "NewMockTestSession should return a non-nil mock")
+	assert.NotNil(t, mock.EXPECT(), "EXPECT should return a non-nil recorder")
+}
+
+func TestMockTestSession_EXPECT(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	recorder := mock.EXPECT()
+	assert.NotNil(t, recorder, "EXPECT should return a non-nil recorder")
+	assert.Equal(t, mock.recorder, recorder, "EXPECT should return the mock's recorder")
+}
+
+func TestMockTestSession_Close(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().Close().Times(1)
+	mock.Close()
+}
+
+func TestMockTestSession_Close_MultipleCalls(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().Close().Times(3)
+	mock.Close()
+	mock.Close()
+	mock.Close()
+}
+
+func TestMockTestSession_CloseConn(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	waitTime := 5
+	mock.EXPECT().CloseConn(waitTime).Times(1)
+	mock.CloseConn(waitTime)
+}
+
+func TestMockTestSession_CloseConn_DifferentWaitTimes(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().CloseConn(0).Times(1)
+	mock.EXPECT().CloseConn(10).Times(1)
+	mock.EXPECT().CloseConn(100).Times(1)
+
+	mock.CloseConn(0)
+	mock.CloseConn(10)
+	mock.CloseConn(100)
+}
+
+func TestMockTestSession_Conn(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	expectedConn := &mockConn{}
+	mock.EXPECT().Conn().Return(expectedConn).Times(1)
+
+	conn := mock.Conn()
+	assert.Equal(t, expectedConn, conn, "Conn should return the expected connection")
+}
+
+func TestMockTestSession_Conn_Nil(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().Conn().Return(nil).Times(1)
+
+	conn := mock.Conn()
+	assert.Nil(t, conn, "Conn should return nil when configured to do so")
+}
+
+func TestMockTestSession_EndPoint(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().EndPoint().Return(nil).Times(1)
+
+	endPoint := mock.EndPoint()
+	assert.Nil(t, endPoint)
+}
+
+func TestMockTestSession_GetActive(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	expectedTime := time.Now()
+	mock.EXPECT().GetActive().Return(expectedTime).Times(1)
+
+	activeTime := mock.GetActive()
+	assert.Equal(t, expectedTime, activeTime, "GetActive should return the expected time")
+}
+
+func TestMockTestSession_GetAttribute(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	key := "testKey"
+	value := "testValue"
+	mock.EXPECT().GetAttribute(key).Return(value).Times(1)
+
+	result := mock.GetAttribute(key)
+	assert.Equal(t, value, result, "GetAttribute should return the expected value")
+}
+
+func TestMockTestSession_GetAttribute_DifferentTypes(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+
+	// String key and value
+	mock.EXPECT().GetAttribute("stringKey").Return("stringValue").Times(1)
+	assert.Equal(t, "stringValue", mock.GetAttribute("stringKey"))
+
+	// Integer key and value
+	mock.EXPECT().GetAttribute(42).Return(100).Times(1)
+	assert.Equal(t, 100, mock.GetAttribute(42))
+
+	// Nil value
+	mock.EXPECT().GetAttribute("nilKey").Return(nil).Times(1)
+	assert.Nil(t, mock.GetAttribute("nilKey"))
+}
+
+func TestMockTestSession_ID(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	expectedID := uint32(12345)
+	mock.EXPECT().ID().Return(expectedID).Times(1)
+
+	id := mock.ID()
+	assert.Equal(t, expectedID, id, "ID should return the expected session ID")
+}
+
+func TestMockTestSession_IncReadPkgNum(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().IncReadPkgNum().Times(1)
+	mock.IncReadPkgNum()
+}
+
+func TestMockTestSession_IncWritePkgNum(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().IncWritePkgNum().Times(1)
+	mock.IncWritePkgNum()
+}
+
+func TestMockTestSession_IsClosed(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().IsClosed().Return(false).Times(1)
+	mock.EXPECT().IsClosed().Return(true).Times(1)
+
+	assert.False(t, mock.IsClosed(), "IsClosed should return false initially")
+	assert.True(t, mock.IsClosed(), "IsClosed should return true after close")
+}
+
+func TestMockTestSession_LocalAddr(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	expectedAddr := "127.0.0.1:8080"
+	mock.EXPECT().LocalAddr().Return(expectedAddr).Times(1)
+
+	addr := mock.LocalAddr()
+	assert.Equal(t, expectedAddr, addr, "LocalAddr should return the expected address")
+}
+
+func TestMockTestSession_RemoteAddr(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	expectedAddr := "192.168.1.1:9090"
+	mock.EXPECT().RemoteAddr().Return(expectedAddr).Times(1)
+
+	addr := mock.RemoteAddr()
+	assert.Equal(t, expectedAddr, addr, "RemoteAddr should return the expected address")
+}
+
+func TestMockTestSession_ReadTimeout(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	expectedTimeout := 30 * time.Second
+	mock.EXPECT().ReadTimeout().Return(expectedTimeout).Times(1)
+
+	timeout := mock.ReadTimeout()
+	assert.Equal(t, expectedTimeout, timeout, "ReadTimeout should return the expected timeout")
+}
+
+func TestMockTestSession_WriteTimeout(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	expectedTimeout := 60 * time.Second
+	mock.EXPECT().WriteTimeout().Return(expectedTimeout).Times(1)
+
+	timeout := mock.WriteTimeout()
+	assert.Equal(t, expectedTimeout, timeout, "WriteTimeout should return the expected timeout")
+}
+
+func TestMockTestSession_RemoveAttribute(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	key := "removeKey"
+	mock.EXPECT().RemoveAttribute(key).Times(1)
+	mock.RemoveAttribute(key)
+}
+
+func TestMockTestSession_Reset(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().Reset().Times(1)
+	mock.Reset()
+}
+
+func TestMockTestSession_Send(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	data := []byte("test data")
+	expectedLen := len(data)
+	mock.EXPECT().Send(data).Return(expectedLen, nil).Times(1)
+
+	n, err := mock.Send(data)
+	assert.Equal(t, expectedLen, n, "Send should return the expected length")
+	assert.NoError(t, err, "Send should not return an error")
+}
+
+func TestMockTestSession_Send_Error(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	data := []byte("test data")
+	expectedErr := errors.New("send error")
+	mock.EXPECT().Send(data).Return(0, expectedErr).Times(1)
+
+	n, err := mock.Send(data)
+	assert.Equal(t, 0, n, "Send should return 0 on error")
+	assert.EqualError(t, err, expectedErr.Error(), "Send should return the expected error")
+}
+
+func TestMockTestSession_SetAttribute(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	key := "attrKey"
+	value := "attrValue"
+	mock.EXPECT().SetAttribute(key, value).Times(1)
+	mock.SetAttribute(key, value)
+}
+
+func TestMockTestSession_SetCompressType(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	compressType := getty.CompressType(1)
+	mock.EXPECT().SetCompressType(compressType).Times(1)
+	mock.SetCompressType(compressType)
+}
+
+func TestMockTestSession_SetCronPeriod(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	period := 1000
+	mock.EXPECT().SetCronPeriod(period).Times(1)
+	mock.SetCronPeriod(period)
+}
+
+func TestMockTestSession_SetEventListener(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().SetEventListener(gomock.Any()).Times(1)
+	mock.SetEventListener(nil)
+}
+
+func TestMockTestSession_SetMaxMsgLen(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	maxLen := 4096
+	mock.EXPECT().SetMaxMsgLen(maxLen).Times(1)
+	mock.SetMaxMsgLen(maxLen)
+}
+
+func TestMockTestSession_SetName(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	name := "testSession"
+	mock.EXPECT().SetName(name).Times(1)
+	mock.SetName(name)
+}
+
+func TestMockTestSession_SetPkgHandler(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().SetPkgHandler(gomock.Any()).Times(1)
+	mock.SetPkgHandler(nil)
+}
+
+func TestMockTestSession_SetReadTimeout(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	timeout := 30 * time.Second
+	mock.EXPECT().SetReadTimeout(timeout).Times(1)
+	mock.SetReadTimeout(timeout)
+}
+
+func TestMockTestSession_SetReader(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().SetReader(gomock.Any()).Times(1)
+	mock.SetReader(nil)
+}
+
+func TestMockTestSession_SetSession(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().SetSession(gomock.Any()).Times(1)
+	mock.SetSession(nil)
+}
+
+func TestMockTestSession_SetWaitTime(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	waitTime := 5 * time.Second
+	mock.EXPECT().SetWaitTime(waitTime).Times(1)
+	mock.SetWaitTime(waitTime)
+}
+
+func TestMockTestSession_SetWriteTimeout(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	timeout := 60 * time.Second
+	mock.EXPECT().SetWriteTimeout(timeout).Times(1)
+	mock.SetWriteTimeout(timeout)
+}
+
+func TestMockTestSession_SetWriter(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().SetWriter(gomock.Any()).Times(1)
+	mock.SetWriter(nil)
+}
+
+func TestMockTestSession_Stat(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	expectedStat := "session stats"
+	mock.EXPECT().Stat().Return(expectedStat).Times(1)
+
+	stat := mock.Stat()
+	assert.Equal(t, expectedStat, stat, "Stat should return the expected statistics")
+}
+
+func TestMockTestSession_UpdateActive(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().UpdateActive().Times(1)
+	mock.UpdateActive()
+}
+
+func TestMockTestSession_WriteBytes(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	data := []byte("test write bytes")
+	expectedLen := len(data)
+	mock.EXPECT().WriteBytes(data).Return(expectedLen, nil).Times(1)
+
+	n, err := mock.WriteBytes(data)
+	assert.Equal(t, expectedLen, n, "WriteBytes should return the expected length")
+	assert.NoError(t, err, "WriteBytes should not return an error")
+}
+
+func TestMockTestSession_WriteBytes_Error(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	data := []byte("test write bytes")
+	expectedErr := errors.New("write error")
+	mock.EXPECT().WriteBytes(data).Return(0, expectedErr).Times(1)
+
+	n, err := mock.WriteBytes(data)
+	assert.Equal(t, 0, n, "WriteBytes should return 0 on error")
+	assert.EqualError(t, err, expectedErr.Error(), "WriteBytes should return the expected error")
+}
+
+func TestMockTestSession_WriteBytesArray(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	data1 := []byte("test1")
+	data2 := []byte("test2")
+	expectedLen := len(data1) + len(data2)
+	mock.EXPECT().WriteBytesArray(data1, data2).Return(expectedLen, nil).Times(1)
+
+	n, err := mock.WriteBytesArray(data1, data2)
+	assert.Equal(t, expectedLen, n, "WriteBytesArray should return the expected length")
+	assert.NoError(t, err, "WriteBytesArray should not return an error")
+}
+
+func TestMockTestSession_WriteBytesArray_EmptyArray(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	mock.EXPECT().WriteBytesArray().Return(0, nil).Times(1)
+
+	n, err := mock.WriteBytesArray()
+	assert.Equal(t, 0, n, "WriteBytesArray with empty array should return 0")
+	assert.NoError(t, err, "WriteBytesArray should not return an error")
+}
+
+func TestMockTestSession_WritePkg(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	pkg := "test package"
+	timeout := 10 * time.Second
+	expectedLen := 100
+	expectedPkgNum := 1
+	mock.EXPECT().WritePkg(pkg, timeout).Return(expectedLen, expectedPkgNum, nil).Times(1)
+
+	length, pkgNum, err := mock.WritePkg(pkg, timeout)
+	assert.Equal(t, expectedLen, length, "WritePkg should return the expected length")
+	assert.Equal(t, expectedPkgNum, pkgNum, "WritePkg should return the expected package number")
+	assert.NoError(t, err, "WritePkg should not return an error")
+}
+
+func TestMockTestSession_WritePkg_Error(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	pkg := "test package"
+	timeout := 10 * time.Second
+	expectedErr := errors.New("write package error")
+	mock.EXPECT().WritePkg(pkg, timeout).Return(0, 0, expectedErr).Times(1)
+
+	length, pkgNum, err := mock.WritePkg(pkg, timeout)
+	assert.Equal(t, 0, length, "WritePkg should return 0 length on error")
+	assert.Equal(t, 0, pkgNum, "WritePkg should return 0 package number on error")
+	assert.EqualError(t, err, expectedErr.Error(), "WritePkg should return the expected error")
+}
+
+// Integration tests for common usage patterns
+
+func TestMockTestSession_FullSessionLifecycle(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+
+	// Setup session
+	mock.EXPECT().SetName("testSession").Times(1)
+	mock.EXPECT().SetReadTimeout(30 * time.Second).Times(1)
+	mock.EXPECT().SetWriteTimeout(60 * time.Second).Times(1)
+	mock.EXPECT().ID().Return(uint32(1)).Times(1)
+
+	// Use session
+	mock.EXPECT().IsClosed().Return(false).Times(1)
+	mock.EXPECT().Send("data").Return(4, nil).Times(1)
+	mock.EXPECT().UpdateActive().Times(1)
+
+	// Close session
+	mock.EXPECT().IsClosed().Return(true).Times(1)
+	mock.EXPECT().Close().Times(1)
+
+	// Execute lifecycle
+	mock.SetName("testSession")
+	mock.SetReadTimeout(30 * time.Second)
+	mock.SetWriteTimeout(60 * time.Second)
+	id := mock.ID()
+	assert.Equal(t, uint32(1), id)
+
+	isClosed := mock.IsClosed()
+	assert.False(t, isClosed)
+
+	n, err := mock.Send("data")
+	assert.Equal(t, 4, n)
+	assert.NoError(t, err)
+
+	mock.UpdateActive()
+
+	isClosed = mock.IsClosed()
+	assert.True(t, isClosed)
+
+	mock.Close()
+}
+
+func TestMockTestSession_AttributeManagement(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+
+	// Set attributes
+	mock.EXPECT().SetAttribute("key1", "value1").Times(1)
+	mock.EXPECT().SetAttribute("key2", 42).Times(1)
+
+	// Get attributes
+	mock.EXPECT().GetAttribute("key1").Return("value1").Times(1)
+	mock.EXPECT().GetAttribute("key2").Return(42).Times(1)
+	mock.EXPECT().GetAttribute("key3").Return(nil).Times(1)
+
+	// Remove attribute
+	mock.EXPECT().RemoveAttribute("key1").Times(1)
+	mock.EXPECT().GetAttribute("key1").Return(nil).Times(1)
+
+	// Execute operations
+	mock.SetAttribute("key1", "value1")
+	mock.SetAttribute("key2", 42)
+
+	val1 := mock.GetAttribute("key1")
+	assert.Equal(t, "value1", val1)
+
+	val2 := mock.GetAttribute("key2")
+	assert.Equal(t, 42, val2)
+
+	val3 := mock.GetAttribute("key3")
+	assert.Nil(t, val3)
+
+	mock.RemoveAttribute("key1")
+	val1After := mock.GetAttribute("key1")
+	assert.Nil(t, val1After)
+}
+
+func TestMockTestSession_MultiplePackageWrites(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	timeout := 5 * time.Second
+
+	// Setup expectations for multiple writes
+	mock.EXPECT().IncWritePkgNum().Times(3)
+	mock.EXPECT().WritePkg("pkg1", timeout).Return(10, 1, nil).Times(1)
+	mock.EXPECT().WritePkg("pkg2", timeout).Return(20, 2, nil).Times(1)
+	mock.EXPECT().WritePkg("pkg3", timeout).Return(30, 3, nil).Times(1)
+
+	// Execute writes
+	mock.IncWritePkgNum()
+	len1, num1, err1 := mock.WritePkg("pkg1", timeout)
+	assert.Equal(t, 10, len1)
+	assert.Equal(t, 1, num1)
+	assert.NoError(t, err1)
+
+	mock.IncWritePkgNum()
+	len2, num2, err2 := mock.WritePkg("pkg2", timeout)
+	assert.Equal(t, 20, len2)
+	assert.Equal(t, 2, num2)
+	assert.NoError(t, err2)
+
+	mock.IncWritePkgNum()
+	len3, num3, err3 := mock.WritePkg("pkg3", timeout)
+	assert.Equal(t, 30, len3)
+	assert.Equal(t, 3, num3)
+	assert.NoError(t, err3)
+}
+
+func TestMockTestSession_ConnectionInfo(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+	conn := &mockConn{}
+
+	mock.EXPECT().Conn().Return(conn).Times(1)
+	mock.EXPECT().LocalAddr().Return("127.0.0.1:8080").Times(1)
+	mock.EXPECT().RemoteAddr().Return("192.168.1.100:9090").Times(1)
+
+	actualConn := mock.Conn()
+	assert.Equal(t, conn, actualConn)
+
+	localAddr := mock.LocalAddr()
+	assert.Equal(t, "127.0.0.1:8080", localAddr)
+
+	remoteAddr := mock.RemoteAddr()
+	assert.Equal(t, "192.168.1.100:9090", remoteAddr)
+}
+
+func TestMockTestSession_TimeoutConfiguration(t *testing.T) {
+	ctrl := gomock.NewController(t)
+	defer ctrl.Finish()
+
+	mock := NewMockTestSession(ctrl)
+
+	readTimeout := 30 * time.Second
+	writeTimeout := 60 * time.Second
+	waitTime := 5 * time.Second
+
+	mock.EXPECT().SetReadTimeout(readTimeout).Times(1)
+	mock.EXPECT().SetWriteTimeout(writeTimeout).Times(1)
+	mock.EXPECT().SetWaitTime(waitTime).Times(1)
+
+	mock.EXPECT().ReadTimeout().Return(readTimeout).Times(1)
+	mock.EXPECT().WriteTimeout().Return(writeTimeout).Times(1)
+
+	// Set timeouts
+	mock.SetReadTimeout(readTimeout)
+	mock.SetWriteTimeout(writeTimeout)
+	mock.SetWaitTime(waitTime)
+
+	// Verify timeouts
+	actualReadTimeout := mock.ReadTimeout()
+	assert.Equal(t, readTimeout, actualReadTimeout)
+
+	actualWriteTimeout := mock.WriteTimeout()
+	assert.Equal(t, writeTimeout, actualWriteTimeout)
+}