You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2025/12/23 04:45:51 UTC

(dubbo-go) branch develop updated: test: add unit test for protocol/dubbo (#3136)

This is an automated email from the ASF dual-hosted git repository.

alexstocks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new 4eb036a62 test: add unit test for protocol/dubbo (#3136)
4eb036a62 is described below

commit 4eb036a6210937e8efcf82c1015da1397bb0d9d5
Author: Akashisang <15...@users.noreply.github.com>
AuthorDate: Tue Dec 23 12:45:47 2025 +0800

    test: add unit test for protocol/dubbo (#3136)
    
    * test: add unit test for protocol/dubbo
---
 protocol/dubbo/dubbo_codec_test.go        | 265 +++++++++++
 protocol/dubbo/dubbo_exporter_test.go     | 219 +++++++++
 protocol/dubbo/impl/codec_test.go         | 224 +++++++++
 protocol/dubbo/impl/hessian_test.go       | 752 +++++++++++++++++++++++++++++-
 protocol/dubbo/impl/package_test.go       | 440 +++++++++++++++++
 protocol/dubbo/impl/request_test.go       | 206 ++++++++
 protocol/dubbo/impl/response_test.go      | 219 +++++++++
 protocol/dubbo/impl/serialization_test.go | 157 +++++++
 protocol/dubbo/impl/serialize_test.go     | 486 +++++++++++++++++++
 protocol/dubbo/opentracing_test.go        | 275 +++++++++++
 10 files changed, 3242 insertions(+), 1 deletion(-)

diff --git a/protocol/dubbo/dubbo_codec_test.go b/protocol/dubbo/dubbo_codec_test.go
new file mode 100644
index 000000000..f57c0efa0
--- /dev/null
+++ b/protocol/dubbo/dubbo_codec_test.go
@@ -0,0 +1,265 @@
+/*
+ * 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 dubbo
+
+import (
+	"testing"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+// TestIsRequest tests isRequest with various bit patterns
+func TestIsRequest(t *testing.T) {
+	codec := &DubboCodec{}
+
+	tests := []struct {
+		desc     string
+		data     []byte
+		expected bool
+	}{
+		{
+			desc:     "request with 0x80 at position 2",
+			data:     []byte{0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00},
+			expected: true,
+		},
+		{
+			desc:     "request with 0xFF at position 2",
+			data:     []byte{0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00},
+			expected: true,
+		},
+		{
+			desc:     "response with 0x00 at position 2",
+			data:     []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+			expected: false,
+		},
+		{
+			desc:     "response with 0x7F at position 2",
+			data:     []byte{0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00},
+			expected: false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			result := codec.isRequest(test.data)
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
+
+// TestDecodeWithInsufficientData tests decode with insufficient header data
+func TestDecodeWithInsufficientData(t *testing.T) {
+	codec := &DubboCodec{}
+
+	// Data shorter than header length
+	data := []byte{0x01, 0x02}
+
+	decodeResult, length, err := codec.Decode(data)
+	assert.Nil(t, decodeResult)
+	assert.Equal(t, 0, length)
+	assert.NoError(t, err)
+}
+
+// TestDecodeWithEmptyData tests decode with empty data
+func TestDecodeWithEmptyData(t *testing.T) {
+	codec := &DubboCodec{}
+
+	data := []byte{}
+
+	decodeResult, length, err := codec.Decode(data)
+	assert.Nil(t, decodeResult)
+	assert.Equal(t, 0, length)
+	assert.NoError(t, err)
+}
+
+// TestCodecType tests that DubboCodec is properly instantiated
+func TestCodecType(t *testing.T) {
+	codec := &DubboCodec{}
+
+	// Verify codec implements the expected interface by checking it has the methods
+	assert.NotNil(t, codec.EncodeRequest)
+	assert.NotNil(t, codec.EncodeResponse)
+	assert.NotNil(t, codec.Decode)
+	assert.NotNil(t, codec.encodeHeartbeatRequest)
+}
+
+// TestIsRequestEdgeCases tests isRequest with edge case bit patterns
+func TestIsRequestEdgeCases(t *testing.T) {
+	codec := &DubboCodec{}
+
+	tests := []struct {
+		desc     string
+		data     []byte
+		expected bool
+	}{
+		{
+			desc:     "bit 0 only",
+			data:     []byte{0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00},
+			expected: false,
+		},
+		{
+			desc:     "bit 1 only",
+			data:     []byte{0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00},
+			expected: false,
+		},
+		{
+			desc:     "bit 2 only",
+			data:     []byte{0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00},
+			expected: false,
+		},
+		{
+			desc:     "multiple bits set including bit 7",
+			data:     []byte{0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+			expected: true,
+		},
+		{
+			desc:     "all bits set except bit 7 (no request bit)",
+			data:     []byte{0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+			expected: false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			result := codec.isRequest(test.data)
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
+
+// TestCodecMultipleInstances tests that multiple codec instances work independently
+func TestCodecMultipleInstances(t *testing.T) {
+	codec1 := &DubboCodec{}
+	codec2 := &DubboCodec{}
+
+	// Both should produce the same results independently
+	testData := []byte{0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+	result1 := codec1.isRequest(testData)
+	result2 := codec2.isRequest(testData)
+
+	assert.Equal(t, result1, result2)
+	assert.True(t, result1)
+}
+
+// TestDecodeDataLength tests various data lengths
+func TestDecodeDataLength(t *testing.T) {
+	codec := &DubboCodec{}
+
+	tests := []struct {
+		desc            string
+		dataLen         int
+		shouldReturnNil bool
+	}{
+		{
+			desc:            "1 byte",
+			dataLen:         1,
+			shouldReturnNil: true,
+		},
+		{
+			desc:            "5 bytes",
+			dataLen:         5,
+			shouldReturnNil: true,
+		},
+		{
+			desc:            "15 bytes",
+			dataLen:         15,
+			shouldReturnNil: true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			data := make([]byte, test.dataLen)
+			decodeResult, _, err := codec.Decode(data)
+
+			if test.shouldReturnNil {
+				assert.Nil(t, decodeResult)
+			}
+			assert.NoError(t, err)
+		})
+	}
+}
+
+// TestIsRequestConsistency tests that isRequest gives consistent results
+func TestIsRequestConsistency(t *testing.T) {
+	codec := &DubboCodec{}
+	data := []byte{0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+	// Call multiple times, should get same result
+	result1 := codec.isRequest(data)
+	result2 := codec.isRequest(data)
+	result3 := codec.isRequest(data)
+
+	assert.Equal(t, result1, result2)
+	assert.Equal(t, result2, result3)
+	assert.True(t, result1)
+}
+
+// TestRequestBitMask tests the request bit mask logic
+func TestRequestBitMask(t *testing.T) {
+	codec := &DubboCodec{}
+
+	// Test boundary values for byte at position 2 with bit 7 (0x80) set
+	tests := []struct {
+		desc      string
+		byteValue byte
+		expected  bool
+	}{
+		{
+			desc:      "0x00 - no bits set",
+			byteValue: 0x00,
+			expected:  false,
+		},
+		{
+			desc:      "0x01 - only bit 0 set",
+			byteValue: 0x01,
+			expected:  false,
+		},
+		{
+			desc:      "0x7F - bits 0-6 set",
+			byteValue: 0x7F,
+			expected:  false,
+		},
+		{
+			desc:      "0x80 - only bit 7 set",
+			byteValue: 0x80,
+			expected:  true,
+		},
+		{
+			desc:      "0x81 - bits 0 and 7 set",
+			byteValue: 0x81,
+			expected:  true,
+		},
+		{
+			desc:      "0xFF - all bits set",
+			byteValue: 0xFF,
+			expected:  true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			data := []byte{0x00, 0x00, test.byteValue, 0x00, 0x00, 0x00, 0x00, 0x00}
+			result := codec.isRequest(data)
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
diff --git a/protocol/dubbo/dubbo_exporter_test.go b/protocol/dubbo/dubbo_exporter_test.go
new file mode 100644
index 000000000..d54bb2a3a
--- /dev/null
+++ b/protocol/dubbo/dubbo_exporter_test.go
@@ -0,0 +1,219 @@
+/*
+ * 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 dubbo
+
+import (
+	"context"
+	"sync"
+	"testing"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+import (
+	"dubbo.apache.org/dubbo-go/v3/common"
+	"dubbo.apache.org/dubbo-go/v3/protocol/base"
+	"dubbo.apache.org/dubbo-go/v3/protocol/result"
+)
+
+// MockInvoker is a simple mock implementation of base.Invoker for testing
+type MockInvoker struct {
+	url       *common.URL
+	available bool
+	destroyed bool
+}
+
+func (m *MockInvoker) GetURL() *common.URL {
+	return m.url
+}
+
+func (m *MockInvoker) Invoke(ctx context.Context, invocation base.Invocation) result.Result {
+	return &result.RPCResult{}
+}
+
+func (m *MockInvoker) IsAvailable() bool {
+	return m.available && !m.destroyed
+}
+
+func (m *MockInvoker) Destroy() {
+	m.destroyed = true
+}
+
+// TestNewDubboExporter tests the NewDubboExporter function
+func TestNewDubboExporter(t *testing.T) {
+	tests := []struct {
+		desc              string
+		key               string
+		invoker           base.Invoker
+		expectedNotNil    bool
+		expectedAvailable bool
+	}{
+		{
+			desc: "with valid invoker",
+			key:  "test_key",
+			invoker: &MockInvoker{
+				url: func() *common.URL {
+					url, _ := common.NewURL("dubbo://localhost:20000/test.TestService?interface=test.TestService&group=test&version=1.0")
+					return url
+				}(),
+				available: true,
+				destroyed: false,
+			},
+			expectedNotNil:    true,
+			expectedAvailable: true,
+		},
+		{
+			desc:              "with nil invoker",
+			key:               "test_key",
+			invoker:           nil,
+			expectedNotNil:    true,
+			expectedAvailable: false,
+		},
+		{
+			desc: "with different key",
+			key:  "another_key",
+			invoker: &MockInvoker{
+				url: func() *common.URL {
+					url, _ := common.NewURL("dubbo://localhost:20000/service?interface=test.Service")
+					return url
+				}(),
+				available: true,
+				destroyed: false,
+			},
+			expectedNotNil:    true,
+			expectedAvailable: true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			exporterMap := &sync.Map{}
+			exporter := NewDubboExporter(test.key, test.invoker, exporterMap)
+
+			assert.NotNil(t, exporter)
+			if test.invoker != nil {
+				assert.Equal(t, test.invoker, exporter.GetInvoker())
+				assert.Equal(t, test.expectedAvailable, exporter.GetInvoker().IsAvailable())
+			} else {
+				assert.Nil(t, exporter.GetInvoker())
+			}
+		})
+	}
+}
+
+// TestDubboExporterGetInvoker tests the GetInvoker method
+func TestDubboExporterGetInvoker(t *testing.T) {
+	tests := []struct {
+		desc      string
+		key       string
+		urlString string
+		checkURL  bool
+	}{
+		{
+			desc:      "get invoker from exporter",
+			key:       "test_key",
+			urlString: "dubbo://localhost:20000/test.TestService?interface=test.TestService",
+			checkURL:  true,
+		},
+		{
+			desc:      "get invoker with group and version",
+			key:       "service_key",
+			urlString: "dubbo://localhost:20000/service?interface=com.example.Service&group=test&version=1.0",
+			checkURL:  true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			exporterMap := &sync.Map{}
+			url, _ := common.NewURL(test.urlString)
+			mockInvoker := &MockInvoker{
+				url:       url,
+				available: true,
+				destroyed: false,
+			}
+
+			exporter := NewDubboExporter(test.key, mockInvoker, exporterMap)
+			retrievedInvoker := exporter.GetInvoker()
+
+			assert.Equal(t, mockInvoker, retrievedInvoker)
+			if test.checkURL {
+				assert.Equal(t, url, retrievedInvoker.GetURL())
+			}
+		})
+	}
+}
+
+// TestDubboExporterMultipleExporters tests creating multiple exporters with different keys coexisting in the same map
+func TestDubboExporterMultipleExporters(t *testing.T) {
+	tests := []struct {
+		desc          string
+		key           string
+		interfaceName string
+	}{
+		{
+			desc:          "service1",
+			key:           "com.example.Service1_key",
+			interfaceName: "com.example.Service1",
+		},
+		{
+			desc:          "service2",
+			key:           "com.example.Service2_key",
+			interfaceName: "com.example.Service2",
+		},
+		{
+			desc:          "test service",
+			key:           "test.Service_key",
+			interfaceName: "test.Service",
+		},
+	}
+
+	// Create a shared exporterMap for all test cases
+	exporterMap := &sync.Map{}
+	exporters := make(map[string]*DubboExporter)
+	mockInvokers := make(map[string]*MockInvoker)
+
+	// Create multiple exporters with different keys in the shared map
+	for _, test := range tests {
+		url, _ := common.NewURL("dubbo://localhost:20000/" + test.interfaceName + "?interface=" + test.interfaceName)
+		mockInvoker := &MockInvoker{
+			url:       url,
+			available: true,
+			destroyed: false,
+		}
+		mockInvokers[test.key] = mockInvoker
+
+		exporter := NewDubboExporter(test.key, mockInvoker, exporterMap)
+		exporters[test.key] = exporter
+	}
+
+	// Verify all exporters coexist in memory - validate the count
+	assert.Equal(t, len(tests), len(exporters), "all exporters should coexist in the exporters map")
+
+	// Verify each exporter has the correct invoker and can be accessed independently
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			exporter, ok := exporters[test.key]
+			assert.True(t, ok, "exporter with key %s should exist in exporters map", test.key)
+			assert.NotNil(t, exporter, "exporter should not be nil")
+			assert.Equal(t, mockInvokers[test.key], exporter.GetInvoker(), "exporter should return the correct invoker")
+		})
+	}
+}
diff --git a/protocol/dubbo/impl/codec_test.go b/protocol/dubbo/impl/codec_test.go
index de45d1eb2..1248df844 100644
--- a/protocol/dubbo/impl/codec_test.go
+++ b/protocol/dubbo/impl/codec_test.go
@@ -87,3 +87,227 @@ func TestDubboPackage_MarshalAndUnmarshal(t *testing.T) {
 	}
 	assert.Equal(t, tmpData, reassembleBody["attachments"])
 }
+
+// TestEncodeHeaderHeartbeat tests EncodeHeader for heartbeat packages
+func TestEncodeHeaderHeartbeat(t *testing.T) {
+	codec := NewDubboCodec(nil)
+	pkg := NewDubboPackage(nil)
+	pkg.Header.Type = PackageHeartbeat
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 12345
+
+	header := codec.EncodeHeader(*pkg)
+	assert.NotNil(t, header)
+	assert.Greater(t, len(header), 0)
+	assert.Equal(t, MAGIC_HIGH, header[0])
+	assert.Equal(t, MAGIC_LOW, header[1])
+}
+
+// TestEncodeHeaderResponse tests EncodeHeader for response packages
+func TestEncodeHeaderResponse(t *testing.T) {
+	codec := NewDubboCodec(nil)
+	pkg := NewDubboPackage(nil)
+	pkg.Header.Type = PackageResponse
+	pkg.Header.ResponseStatus = Response_OK
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 99999
+
+	header := codec.EncodeHeader(*pkg)
+	assert.NotNil(t, header)
+	assert.Equal(t, MAGIC_HIGH, header[0])
+	assert.Equal(t, MAGIC_LOW, header[1])
+	assert.Equal(t, Response_OK, header[3])
+}
+
+// TestEncodeHeaderResponseWithError tests EncodeHeader for error response packages
+func TestEncodeHeaderResponseWithError(t *testing.T) {
+	codec := NewDubboCodec(nil)
+	pkg := NewDubboPackage(nil)
+	pkg.Header.Type = PackageResponse
+	pkg.Header.ResponseStatus = Response_SERVICE_ERROR
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 11111
+
+	header := codec.EncodeHeader(*pkg)
+	assert.NotNil(t, header)
+	assert.Equal(t, Response_SERVICE_ERROR, header[3])
+}
+
+// TestEncodeHeaderRequestTwoWay tests EncodeHeader for two-way request packages
+func TestEncodeHeaderRequestTwoWay(t *testing.T) {
+	codec := NewDubboCodec(nil)
+	pkg := NewDubboPackage(nil)
+	pkg.Header.Type = PackageRequest_TwoWay
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 22222
+
+	header := codec.EncodeHeader(*pkg)
+	assert.NotNil(t, header)
+	assert.Greater(t, len(header), 0)
+}
+
+// TestProtocolCodecSetSerializer tests SetSerializer method of ProtocolCodec
+func TestProtocolCodecSetSerializer(t *testing.T) {
+	codec := NewDubboCodec(nil)
+	serializer := &HessianSerializer{}
+
+	codec.SetSerializer(serializer)
+	assert.NotNil(t, codec.serializer)
+}
+
+// TestPackageResponseWorkflow tests response package workflow
+func TestPackageResponseWorkflow(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.Type = PackageResponse
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 99999
+	pkg.Header.ResponseStatus = Response_OK
+	pkg.Body = "response"
+	pkg.SetSerializer(mockSerializer)
+
+	assert.False(t, pkg.IsHeartBeat())
+	assert.False(t, pkg.IsRequest())
+	assert.True(t, pkg.IsResponse())
+	assert.False(t, pkg.IsResponseWithException())
+
+	data, err := pkg.Marshal()
+	assert.NoError(t, err)
+	assert.NotNil(t, data)
+}
+
+// TestPackageRequestWorkflow tests request package workflow
+func TestPackageRequestWorkflow(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.Type = PackageRequest
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 66666
+	pkg.Service.Interface = "TestService"
+	pkg.Service.Path = "/dubbo"
+	pkg.Service.Method = "test"
+	pkg.Body = []any{"arg1"}
+	pkg.SetSerializer(mockSerializer)
+
+	assert.False(t, pkg.IsHeartBeat())
+	assert.True(t, pkg.IsRequest())
+	assert.False(t, pkg.IsResponse())
+
+	data, err := pkg.Marshal()
+	assert.NoError(t, err)
+	assert.NotNil(t, data)
+}
+
+// TestPackageBodyManipulation tests body manipulation methods
+func TestPackageBodyManipulation(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+
+	testBodies := []any{
+		"string",
+		123,
+		[]string{"a", "b"},
+		map[string]any{"key": "value"},
+	}
+
+	for _, body := range testBodies {
+		pkg.SetBody(body)
+		assert.Equal(t, body, pkg.GetBody())
+	}
+}
+
+// TestPackageIDManipulation tests ID manipulation
+func TestPackageIDManipulation(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+
+	ids := []int64{1, 100, 1000, 999999, 9223372036854775807}
+
+	for _, id := range ids {
+		pkg.SetID(id)
+		assert.Equal(t, id, pkg.Header.ID)
+	}
+}
+
+// TestPackageServiceManipulation tests service manipulation
+func TestPackageServiceManipulation(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+
+	services := []Service{
+		{Path: "/a", Interface: "InterfaceA"},
+		{Path: "/b", Interface: "InterfaceB", Version: "1.0"},
+		{Path: "/c", Interface: "InterfaceC", Group: "g1", Version: "2.0"},
+	}
+
+	for _, svc := range services {
+		pkg.SetService(svc)
+		retrieved := pkg.GetService()
+		assert.Equal(t, svc.Path, retrieved.Path)
+		assert.Equal(t, svc.Interface, retrieved.Interface)
+		assert.Equal(t, svc.Version, retrieved.Version)
+		assert.Equal(t, svc.Group, retrieved.Group)
+	}
+}
+
+// TestPackageHeaderManipulation tests header manipulation
+func TestPackageHeaderManipulation(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+
+	headers := []DubboHeader{
+		{ID: 1, BodyLen: 100, Type: PackageRequest},
+		{ID: 2, BodyLen: 200, Type: PackageResponse, ResponseStatus: Response_OK},
+		{ID: 3, BodyLen: 300, Type: PackageHeartbeat, SerialID: constant.SHessian2},
+	}
+
+	for _, header := range headers {
+		pkg.SetHeader(header)
+		retrieved := pkg.GetHeader()
+		assert.Equal(t, header.ID, retrieved.ID)
+		assert.Equal(t, header.BodyLen, retrieved.BodyLen)
+		assert.Equal(t, header.Type, retrieved.Type)
+	}
+}
+
+// TestPackageResponseStatusWorkflow tests response status workflow
+func TestPackageResponseStatusWorkflow(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+	pkg.Header.Type = PackageResponse
+
+	statuses := []struct {
+		status byte
+		name   string
+	}{
+		{Response_OK, "OK"},
+		{Response_CLIENT_TIMEOUT, "CLIENT_TIMEOUT"},
+		{Response_SERVER_TIMEOUT, "SERVER_TIMEOUT"},
+		{Response_BAD_REQUEST, "BAD_REQUEST"},
+	}
+
+	for _, s := range statuses {
+		pkg.SetResponseStatus(s.status)
+		assert.Equal(t, s.status, pkg.Header.ResponseStatus)
+	}
+}
+
+// TestDubboPackageIntegrationWithLoadSerializer tests integration with LoadSerializer
+func TestDubboPackageIntegrationWithLoadSerializer(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.Type = PackageRequest
+	pkg.Header.ID = 55555
+	pkg.Service.Interface = "TestService"
+	pkg.Body = []any{"test"}
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+
+	data, err := pkg.Marshal()
+	assert.NoError(t, err)
+	assert.NotNil(t, data)
+	assert.Greater(t, data.Len(), 0)
+}
diff --git a/protocol/dubbo/impl/hessian_test.go b/protocol/dubbo/impl/hessian_test.go
index 73c98ea9f..5cc4303f3 100644
--- a/protocol/dubbo/impl/hessian_test.go
+++ b/protocol/dubbo/impl/hessian_test.go
@@ -18,15 +18,22 @@
 package impl
 
 import (
+	"errors"
 	"testing"
+	"time"
 )
 
 import (
-	"github.com/apache/dubbo-go-hessian2"
+	hessian "github.com/apache/dubbo-go-hessian2"
+	"github.com/apache/dubbo-go-hessian2/java_exception"
 
 	"github.com/stretchr/testify/assert"
 )
 
+import (
+	"dubbo.apache.org/dubbo-go/v3/common"
+)
+
 const (
 	dubboParam = "org.apache.dubbo.param"
 	dubboPojo  = "org.apache.dubbo.pojo"
@@ -59,6 +66,265 @@ func TestGetArgType(t *testing.T) {
 	t.Run("param", func(t *testing.T) {
 		assert.Equal(t, dubboParam, getArgType(&Param{}))
 	})
+
+	t.Run("nil", func(t *testing.T) {
+		assert.Equal(t, "V", getArgType(nil))
+	})
+
+	t.Run("bool", func(t *testing.T) {
+		assert.Equal(t, "Z", getArgType(true))
+	})
+
+	t.Run("bool array", func(t *testing.T) {
+		assert.Equal(t, "[Z", getArgType([]bool{true, false}))
+	})
+
+	t.Run("byte", func(t *testing.T) {
+		assert.Equal(t, "B", getArgType(byte(1)))
+	})
+
+	t.Run("byte array", func(t *testing.T) {
+		assert.Equal(t, "[B", getArgType([]byte{1, 2, 3}))
+	})
+
+	t.Run("int8", func(t *testing.T) {
+		assert.Equal(t, "B", getArgType(int8(1)))
+	})
+
+	t.Run("int8 array", func(t *testing.T) {
+		assert.Equal(t, "[B", getArgType([]int8{1, 2, 3}))
+	})
+
+	t.Run("int16", func(t *testing.T) {
+		assert.Equal(t, "S", getArgType(int16(1)))
+	})
+
+	t.Run("int16 array", func(t *testing.T) {
+		assert.Equal(t, "[S", getArgType([]int16{1, 2, 3}))
+	})
+
+	t.Run("uint16", func(t *testing.T) {
+		assert.Equal(t, "C", getArgType(uint16(1)))
+	})
+
+	t.Run("uint16 array", func(t *testing.T) {
+		assert.Equal(t, "[C", getArgType([]uint16{1, 2, 3}))
+	})
+
+	t.Run("int", func(t *testing.T) {
+		assert.Equal(t, "J", getArgType(int(1)))
+	})
+
+	t.Run("int array", func(t *testing.T) {
+		assert.Equal(t, "[J", getArgType([]int{1, 2, 3}))
+	})
+
+	t.Run("int32", func(t *testing.T) {
+		assert.Equal(t, "I", getArgType(int32(1)))
+	})
+
+	t.Run("int32 array", func(t *testing.T) {
+		assert.Equal(t, "[I", getArgType([]int32{1, 2, 3}))
+	})
+
+	t.Run("int64", func(t *testing.T) {
+		assert.Equal(t, "J", getArgType(int64(1)))
+	})
+
+	t.Run("int64 array", func(t *testing.T) {
+		assert.Equal(t, "[J", getArgType([]int64{1, 2, 3}))
+	})
+
+	t.Run("time.Time", func(t *testing.T) {
+		assert.Equal(t, "java.util.Date", getArgType(time.Now()))
+	})
+
+	t.Run("time.Time array", func(t *testing.T) {
+		assert.Equal(t, "[Ljava.util.Date", getArgType([]time.Time{time.Now()}))
+	})
+
+	t.Run("float32", func(t *testing.T) {
+		assert.Equal(t, "F", getArgType(float32(1.0)))
+	})
+
+	t.Run("float32 array", func(t *testing.T) {
+		assert.Equal(t, "[F", getArgType([]float32{1.0, 2.0}))
+	})
+
+	t.Run("float64", func(t *testing.T) {
+		assert.Equal(t, "D", getArgType(float64(1.0)))
+	})
+
+	t.Run("float64 array", func(t *testing.T) {
+		assert.Equal(t, "[D", getArgType([]float64{1.0, 2.0}))
+	})
+
+	t.Run("string", func(t *testing.T) {
+		assert.Equal(t, "java.lang.String", getArgType("test"))
+	})
+
+	t.Run("string array", func(t *testing.T) {
+		assert.Equal(t, "[Ljava.lang.String;", getArgType([]string{"test1", "test2"}))
+	})
+
+	t.Run("map[any]any", func(t *testing.T) {
+		assert.Equal(t, "java.util.Map", getArgType(map[any]any{"key": "value"}))
+	})
+
+	t.Run("map[string]int", func(t *testing.T) {
+		assert.Equal(t, "java.util.Map", getArgType(map[string]int{"key": 1}))
+	})
+
+	t.Run("pointer types", func(t *testing.T) {
+		v := int8(1)
+		assert.Equal(t, "java.lang.Byte", getArgType(&v))
+
+		v2 := int16(1)
+		assert.Equal(t, "java.lang.Short", getArgType(&v2))
+
+		v3 := uint16(1)
+		assert.Equal(t, "java.lang.Character", getArgType(&v3))
+
+		v4 := int(1)
+		assert.Equal(t, "java.lang.Long", getArgType(&v4))
+
+		v5 := int32(1)
+		assert.Equal(t, "java.lang.Integer", getArgType(&v5))
+
+		v6 := int64(1)
+		assert.Equal(t, "java.lang.Long", getArgType(&v6))
+
+		v7 := float32(1.0)
+		assert.Equal(t, "java.lang.Float", getArgType(&v7))
+
+		v8 := float64(1.0)
+		assert.Equal(t, "java.lang.Double", getArgType(&v8))
+	})
+
+	t.Run("slice of structs", func(t *testing.T) {
+		assert.Equal(t, "[Ljava.lang.Object;", getArgType([]Pojo{{}, {}}))
+	})
+
+	t.Run("slice of string", func(t *testing.T) {
+		assert.Equal(t, "[Ljava.lang.String;", getArgType([]string{"a", "b"}))
+	})
+
+	t.Run("generic object", func(t *testing.T) {
+		type GenericStruct struct {
+			Field string
+		}
+		assert.Equal(t, "java.lang.Object", getArgType(&GenericStruct{Field: "test"}))
+	})
+}
+
+func TestGetArgsTypeList(t *testing.T) {
+	t.Run("multiple types", func(t *testing.T) {
+		args := []any{int32(1), "test", true, float64(1.0)}
+		types, err := GetArgsTypeList(args)
+		assert.NoError(t, err)
+		assert.Equal(t, "ILjava/lang/String;ZD", types)
+	})
+
+	t.Run("with pojo", func(t *testing.T) {
+		args := []any{&Pojo{}, "test"}
+		types, err := GetArgsTypeList(args)
+		assert.NoError(t, err)
+		assert.Equal(t, "Lorg/apache/dubbo/pojo;Ljava/lang/String;", types)
+	})
+
+	t.Run("with array", func(t *testing.T) {
+		args := []any{[]string{"a", "b"}}
+		types, err := GetArgsTypeList(args)
+		assert.NoError(t, err)
+		assert.Equal(t, "[Ljava/lang/String;", types)
+	})
+
+	t.Run("empty args", func(t *testing.T) {
+		args := []any{}
+		types, err := GetArgsTypeList(args)
+		assert.NoError(t, err)
+		assert.Equal(t, "", types)
+	})
+}
+
+func TestToMapStringInterface(t *testing.T) {
+	t.Run("normal map", func(t *testing.T) {
+		origin := map[any]any{
+			"key1": "value1",
+			"key2": 123,
+		}
+		result := ToMapStringInterface(origin)
+		assert.Equal(t, "value1", result["key1"])
+		assert.Equal(t, 123, result["key2"])
+	})
+
+	t.Run("with nil value", func(t *testing.T) {
+		origin := map[any]any{
+			"key1": nil,
+			"key2": "value2",
+		}
+		result := ToMapStringInterface(origin)
+		assert.Equal(t, "", result["key1"])
+		assert.Equal(t, "value2", result["key2"])
+	})
+
+	t.Run("with non-string key", func(t *testing.T) {
+		origin := map[any]any{
+			123:    "value1",
+			"key2": "value2",
+		}
+		result := ToMapStringInterface(origin)
+		assert.Equal(t, 1, len(result))
+		assert.Equal(t, "value2", result["key2"])
+	})
+}
+
+func TestVersion2Int(t *testing.T) {
+	tests := []struct {
+		name     string
+		version  string
+		expected int
+	}{
+		{"version 2.0.10", "2.0.10", 2001000},
+		{"version 2.6.2", "2.6.2", 2060200},
+		{"version 2.7.0", "2.7.0", 2070000},
+		{"version 2.0.1", "2.0.1", 2000100},
+		{"version 3.0.0", "3.0.0", 3000000},
+		{"invalid version", "invalid", -1},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			result := version2Int(tt.version)
+			assert.Equal(t, tt.expected, result)
+		})
+	}
+}
+
+func TestIsSupportResponseAttachment(t *testing.T) {
+	t.Run("empty version", func(t *testing.T) {
+		assert.False(t, isSupportResponseAttachment(""))
+	})
+
+	t.Run("version 2.0.10", func(t *testing.T) {
+		assert.False(t, isSupportResponseAttachment("2.0.10"))
+	})
+
+	t.Run("version 2.6.2", func(t *testing.T) {
+		assert.False(t, isSupportResponseAttachment("2.6.2"))
+	})
+
+	t.Run("version 2.7.0", func(t *testing.T) {
+		assert.True(t, isSupportResponseAttachment("2.7.0"))
+	})
+
+	t.Run("version 3.0.0", func(t *testing.T) {
+		assert.True(t, isSupportResponseAttachment("3.0.0"))
+	})
+
+	t.Run("invalid version", func(t *testing.T) {
+		assert.False(t, isSupportResponseAttachment("invalid"))
+	})
 }
 
 func TestMarshalRequestWithTypedNilPointer(t *testing.T) {
@@ -103,3 +369,487 @@ func TestMarshalRequestWithNonNilPointer(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotNil(t, data)
 }
+
+func TestMarshalRequest(t *testing.T) {
+	t.Run("basic request", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		pkg := DubboPackage{
+			Service: Service{
+				Path:      "com.test.Service",
+				Interface: "com.test.Service",
+				Version:   "1.0.0",
+				Method:    "test",
+				Group:     "testGroup",
+				Timeout:   time.Second * 5,
+			},
+			Body: &RequestPayload{
+				Params:      []any{int32(123), "test"},
+				Attachments: map[string]any{},
+			},
+		}
+
+		data, err := marshalRequest(encoder, pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+
+	t.Run("request with invalid params", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		pkg := DubboPackage{
+			Service: Service{
+				Path:    "test.Path",
+				Version: "1.0.0",
+				Method:  "Echo",
+			},
+			Body: &RequestPayload{
+				Params:      "not a slice",
+				Attachments: map[string]any{},
+			},
+		}
+
+		_, err := marshalRequest(encoder, pkg)
+		assert.Error(t, err)
+	})
+}
+
+func TestMarshalResponse(t *testing.T) {
+	t.Run("heartbeat response", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		pkg := DubboPackage{
+			Header: DubboHeader{
+				Type:           PackageHeartbeat | PackageResponse,
+				ResponseStatus: Response_OK,
+			},
+			Body: &ResponsePayload{
+				Attachments: map[string]any{},
+			},
+		}
+
+		data, err := marshalResponse(encoder, pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+
+	t.Run("response with value", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		pkg := DubboPackage{
+			Header: DubboHeader{
+				Type:           PackageResponse,
+				ResponseStatus: Response_OK,
+			},
+			Body: &ResponsePayload{
+				RspObj:      "test response",
+				Attachments: map[string]any{},
+			},
+		}
+
+		data, err := marshalResponse(encoder, pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+
+	t.Run("response with null value", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		pkg := DubboPackage{
+			Header: DubboHeader{
+				Type:           PackageResponse,
+				ResponseStatus: Response_OK,
+			},
+			Body: &ResponsePayload{
+				RspObj:      nil,
+				Attachments: map[string]any{},
+			},
+		}
+
+		data, err := marshalResponse(encoder, pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+
+	t.Run("response with exception", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		pkg := DubboPackage{
+			Header: DubboHeader{
+				Type:           PackageResponse,
+				ResponseStatus: Response_OK,
+			},
+			Body: &ResponsePayload{
+				Exception:   errors.New("test error"),
+				Attachments: map[string]any{},
+			},
+		}
+
+		data, err := marshalResponse(encoder, pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+
+	t.Run("response with throwable exception", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		pkg := DubboPackage{
+			Header: DubboHeader{
+				Type:           PackageResponse,
+				ResponseStatus: Response_OK,
+			},
+			Body: &ResponsePayload{
+				Exception:   java_exception.NewThrowable("test throwable"),
+				Attachments: map[string]any{},
+			},
+		}
+
+		data, err := marshalResponse(encoder, pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+
+	t.Run("response with attachments", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		pkg := DubboPackage{
+			Header: DubboHeader{
+				Type:           PackageResponse,
+				ResponseStatus: Response_OK,
+			},
+			Body: &ResponsePayload{
+				RspObj: "test",
+				Attachments: map[string]any{
+					DUBBO_VERSION_KEY: "2.7.0",
+					"custom":          "value",
+				},
+			},
+		}
+
+		data, err := marshalResponse(encoder, pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+
+	t.Run("response with error status", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		pkg := DubboPackage{
+			Header: DubboHeader{
+				Type:           PackageResponse,
+				ResponseStatus: Response_SERVER_ERROR,
+			},
+			Body: &ResponsePayload{
+				Exception: errors.New("server error"),
+			},
+		}
+
+		data, err := marshalResponse(encoder, pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+}
+
+func TestUnmarshalRequestBody(t *testing.T) {
+	t.Run("basic request unmarshal", func(t *testing.T) {
+		// Prepare encoded request
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode("2.0.2")                     // dubbo version
+		_ = encoder.Encode("com.test.Service")          // target
+		_ = encoder.Encode("1.0.0")                     // service version
+		_ = encoder.Encode("test")                      // method
+		_ = encoder.Encode("Ljava/lang/String;")        // args types
+		_ = encoder.Encode("hello")                     // args
+		_ = encoder.Encode(map[any]any{"key": "value"}) // attachments
+
+		pkg := &DubboPackage{}
+		err := unmarshalRequestBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, pkg.Body)
+
+		body, ok := pkg.Body.(map[string]any)
+		assert.True(t, ok)
+		assert.Equal(t, "2.0.2", body["dubboVersion"])
+		assert.Equal(t, "Ljava/lang/String;", body["argsTypes"])
+		assert.NotNil(t, body["attachments"])
+	})
+
+	t.Run("request with multiple args", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode("2.0.2")
+		_ = encoder.Encode("com.test.Service")
+		_ = encoder.Encode("1.0.0")
+		_ = encoder.Encode("test")
+		_ = encoder.Encode("ILjava/lang/String;")
+		_ = encoder.Encode(int32(123))
+		_ = encoder.Encode("test")
+		_ = encoder.Encode(map[any]any{"key": "value"})
+
+		pkg := &DubboPackage{}
+		err := unmarshalRequestBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+
+		body, ok := pkg.GetBody().(map[string]any)
+		assert.True(t, ok)
+		args := body["args"].([]any)
+		assert.Equal(t, 2, len(args))
+	})
+
+	t.Run("request with nil attachments", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode("2.0.2")
+		_ = encoder.Encode("com.test.Service")
+		_ = encoder.Encode("1.0.0")
+		_ = encoder.Encode("test")
+		_ = encoder.Encode("")
+		_ = encoder.Encode(nil)
+
+		pkg := &DubboPackage{}
+		err := unmarshalRequestBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+	})
+}
+
+func TestUnmarshalResponseBody(t *testing.T) {
+	t.Run("response with value", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode(RESPONSE_VALUE)
+		_ = encoder.Encode("test response")
+
+		// Need to set RspObj for ReflectResponse to work
+		rspObj := ""
+		pkg := &DubboPackage{
+			Body: &ResponsePayload{
+				RspObj: &rspObj,
+			},
+		}
+		err := unmarshalResponseBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+		assert.Equal(t, "test response", rspObj)
+	})
+
+	t.Run("response with value and attachments", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode(RESPONSE_VALUE_WITH_ATTACHMENTS)
+		_ = encoder.Encode("test response")
+		_ = encoder.Encode(map[any]any{"key": "value"})
+
+		rspObj := ""
+		pkg := &DubboPackage{
+			Body: &ResponsePayload{
+				RspObj: &rspObj,
+			},
+		}
+		err := unmarshalResponseBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+
+		response := EnsureResponsePayload(pkg.Body)
+		assert.NotNil(t, response.Attachments)
+		assert.Equal(t, "value", response.Attachments["key"])
+	})
+
+	t.Run("response with exception", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode(RESPONSE_WITH_EXCEPTION)
+		_ = encoder.Encode(java_exception.NewThrowable("test error"))
+
+		pkg := &DubboPackage{}
+		err := unmarshalResponseBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+
+		response := EnsureResponsePayload(pkg.Body)
+		assert.NotNil(t, response.Exception)
+	})
+
+	t.Run("response with exception and attachments", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode(RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS)
+		_ = encoder.Encode(java_exception.NewThrowable("test error"))
+		_ = encoder.Encode(map[any]any{"key": "value"})
+
+		pkg := &DubboPackage{}
+		err := unmarshalResponseBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+
+		response := EnsureResponsePayload(pkg.Body)
+		assert.NotNil(t, response.Exception)
+		assert.NotNil(t, response.Attachments)
+	})
+
+	t.Run("response with null value", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode(RESPONSE_NULL_VALUE)
+
+		pkg := &DubboPackage{}
+		err := unmarshalResponseBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+	})
+
+	t.Run("response with null value and attachments", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode(RESPONSE_NULL_VALUE_WITH_ATTACHMENTS)
+		_ = encoder.Encode(map[any]any{"key": "value"})
+
+		pkg := &DubboPackage{}
+		err := unmarshalResponseBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+
+		response := EnsureResponsePayload(pkg.Body)
+		assert.NotNil(t, response.Attachments)
+	})
+
+	t.Run("response with non-error exception", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode(RESPONSE_WITH_EXCEPTION)
+		_ = encoder.Encode("string exception")
+
+		pkg := &DubboPackage{}
+		err := unmarshalResponseBody(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+
+		response := EnsureResponsePayload(pkg.Body)
+		assert.NotNil(t, response.Exception)
+	})
+
+	t.Run("response with invalid attachments", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode(RESPONSE_VALUE_WITH_ATTACHMENTS)
+		_ = encoder.Encode("test")
+		_ = encoder.Encode("invalid attachments")
+
+		pkg := &DubboPackage{}
+		err := unmarshalResponseBody(encoder.Buffer(), pkg)
+		assert.Error(t, err)
+	})
+}
+
+func TestBuildServerSidePackageBody(t *testing.T) {
+	// Register a test service
+	common.ServiceMap.Register("com.test.Interface", "dubbo", "testGroup", "1.0.0", &TestService{})
+
+	t.Run("build package body", func(t *testing.T) {
+		req := []any{
+			"2.0.2",
+			"com.test.Path",
+			"1.0.0",
+			"test",
+			"Ljava/lang/String;",
+			[]any{"arg1"},
+			map[string]any{
+				"path":      "com.test.Path",
+				"interface": "com.test.Interface",
+				"group":     "testGroup",
+			},
+		}
+
+		pkg := &DubboPackage{
+			Body: req,
+		}
+
+		buildServerSidePackageBody(pkg)
+
+		body, ok := pkg.GetBody().(map[string]any)
+		assert.True(t, ok)
+		assert.Equal(t, "2.0.2", body["dubboVersion"])
+		assert.Equal(t, "Ljava/lang/String;", body["argsTypes"])
+		assert.NotNil(t, body["attachments"])
+	})
+
+	t.Run("empty body", func(t *testing.T) {
+		pkg := &DubboPackage{
+			Body: []any{},
+		}
+
+		buildServerSidePackageBody(pkg)
+		// Should not panic
+	})
+}
+
+type TestService struct{}
+
+func TestHessianSerializer_Marshal(t *testing.T) {
+	serializer := HessianSerializer{}
+
+	t.Run("marshal request", func(t *testing.T) {
+		pkg := DubboPackage{
+			Header: DubboHeader{
+				Type: PackageRequest,
+			},
+			Service: Service{
+				Path:    "test.Service",
+				Version: "1.0.0",
+				Method:  "test",
+			},
+			Body: &RequestPayload{
+				Params:      []any{int32(123)},
+				Attachments: map[string]any{},
+			},
+		}
+
+		data, err := serializer.Marshal(pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+
+	t.Run("marshal response", func(t *testing.T) {
+		pkg := DubboPackage{
+			Header: DubboHeader{
+				Type:           PackageResponse,
+				ResponseStatus: Response_OK,
+			},
+			Body: &ResponsePayload{
+				RspObj:      "test",
+				Attachments: map[string]any{},
+			},
+		}
+
+		data, err := serializer.Marshal(pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, data)
+	})
+}
+
+func TestHessianSerializer_Unmarshal(t *testing.T) {
+	serializer := HessianSerializer{}
+
+	t.Run("unmarshal heartbeat", func(t *testing.T) {
+		pkg := &DubboPackage{
+			Header: DubboHeader{
+				Type: PackageHeartbeat | PackageResponse,
+			},
+		}
+
+		err := serializer.Unmarshal([]byte{}, pkg)
+		assert.NoError(t, err)
+	})
+
+	t.Run("unmarshal request", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode("2.0.2")
+		_ = encoder.Encode("com.test.Service")
+		_ = encoder.Encode("1.0.0")
+		_ = encoder.Encode("test")
+		_ = encoder.Encode("")
+		_ = encoder.Encode(map[any]any{"key": "value"})
+
+		pkg := &DubboPackage{
+			Header: DubboHeader{
+				Type: PackageRequest,
+			},
+		}
+
+		err := serializer.Unmarshal(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+	})
+
+	t.Run("unmarshal response", func(t *testing.T) {
+		encoder := hessian.NewEncoder()
+		_ = encoder.Encode(RESPONSE_VALUE)
+		_ = encoder.Encode("test")
+
+		rspObj := ""
+		pkg := &DubboPackage{
+			Header: DubboHeader{
+				Type: PackageResponse,
+			},
+			Body: &ResponsePayload{
+				RspObj: &rspObj,
+			},
+		}
+
+		err := serializer.Unmarshal(encoder.Buffer(), pkg)
+		assert.NoError(t, err)
+		assert.Equal(t, "test", rspObj)
+	})
+}
diff --git a/protocol/dubbo/impl/package_test.go b/protocol/dubbo/impl/package_test.go
new file mode 100644
index 000000000..7d3beea1e
--- /dev/null
+++ b/protocol/dubbo/impl/package_test.go
@@ -0,0 +1,440 @@
+/*
+ * 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 impl
+
+import (
+	"bytes"
+	"testing"
+	"time"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+// TestNewDubboPackage tests creating a new DubboPackage
+func TestNewDubboPackage(t *testing.T) {
+	tests := []struct {
+		desc      string
+		data      *bytes.Buffer
+		expectNil bool
+	}{
+		{
+			desc:      "with nil data",
+			data:      nil,
+			expectNil: false,
+		},
+		{
+			desc:      "with empty buffer",
+			data:      bytes.NewBuffer([]byte{}),
+			expectNil: false,
+		},
+		{
+			desc:      "with buffer containing data",
+			data:      bytes.NewBuffer([]byte{0x01, 0x02, 0x03}),
+			expectNil: false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			pkg := NewDubboPackage(test.data)
+
+			if test.expectNil {
+				assert.Nil(t, pkg)
+			} else {
+				assert.NotNil(t, pkg)
+				assert.NotNil(t, pkg.Codec)
+				assert.Nil(t, pkg.Body)
+				assert.Nil(t, pkg.Err)
+			}
+		})
+	}
+}
+
+// TestDubboPackageIsHeartBeat tests IsHeartBeat method
+func TestDubboPackageIsHeartBeat(t *testing.T) {
+	tests := []struct {
+		desc       string
+		headerType PackageType
+		expected   bool
+	}{
+		{
+			desc:       "heartbeat package",
+			headerType: PackageHeartbeat,
+			expected:   true,
+		},
+		{
+			desc:       "request package",
+			headerType: PackageRequest,
+			expected:   false,
+		},
+		{
+			desc:       "response package",
+			headerType: PackageResponse,
+			expected:   false,
+		},
+		{
+			desc:       "heartbeat with other flags",
+			headerType: PackageHeartbeat | PackageRequest,
+			expected:   true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Header.Type = test.headerType
+
+			result := pkg.IsHeartBeat()
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
+
+// TestDubboPackageIsRequest tests IsRequest method
+func TestDubboPackageIsRequest(t *testing.T) {
+	tests := []struct {
+		desc       string
+		headerType PackageType
+		expected   bool
+	}{
+		{
+			desc:       "request package",
+			headerType: PackageRequest,
+			expected:   true,
+		},
+		{
+			desc:       "two way request package",
+			headerType: PackageRequest_TwoWay,
+			expected:   true,
+		},
+		{
+			desc:       "response package",
+			headerType: PackageResponse,
+			expected:   false,
+		},
+		{
+			desc:       "heartbeat package",
+			headerType: PackageHeartbeat,
+			expected:   false,
+		},
+		{
+			desc:       "request with twoway flag",
+			headerType: PackageRequest | PackageRequest_TwoWay,
+			expected:   true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Header.Type = test.headerType
+
+			result := pkg.IsRequest()
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
+
+// TestDubboPackageIsResponse tests IsResponse method
+func TestDubboPackageIsResponse(t *testing.T) {
+	tests := []struct {
+		desc       string
+		headerType PackageType
+		expected   bool
+	}{
+		{
+			desc:       "response package",
+			headerType: PackageResponse,
+			expected:   true,
+		},
+		{
+			desc:       "request package",
+			headerType: PackageRequest,
+			expected:   false,
+		},
+		{
+			desc:       "heartbeat package",
+			headerType: PackageHeartbeat,
+			expected:   false,
+		},
+		{
+			desc:       "response with exception",
+			headerType: PackageResponse | PackageResponse_Exception,
+			expected:   false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Header.Type = test.headerType
+
+			result := pkg.IsResponse()
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
+
+// TestDubboPackageIsResponseWithException tests IsResponseWithException method
+func TestDubboPackageIsResponseWithException(t *testing.T) {
+	tests := []struct {
+		desc       string
+		headerType PackageType
+		expected   bool
+	}{
+		{
+			desc:       "response with exception",
+			headerType: PackageResponse | PackageResponse_Exception,
+			expected:   true,
+		},
+		{
+			desc:       "response without exception",
+			headerType: PackageResponse,
+			expected:   false,
+		},
+		{
+			desc:       "request package",
+			headerType: PackageRequest,
+			expected:   false,
+		},
+		{
+			desc:       "only exception flag",
+			headerType: PackageResponse_Exception,
+			expected:   false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Header.Type = test.headerType
+
+			result := pkg.IsResponseWithException()
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
+
+// TestDubboPackageGetBodyLen tests GetBodyLen method
+func TestDubboPackageGetBodyLen(t *testing.T) {
+	tests := []struct {
+		desc     string
+		bodyLen  int
+		expected int
+	}{
+		{
+			desc:     "zero length body",
+			bodyLen:  0,
+			expected: 0,
+		},
+		{
+			desc:     "100 bytes body",
+			bodyLen:  100,
+			expected: 100,
+		},
+		{
+			desc:     "1000 bytes body",
+			bodyLen:  1000,
+			expected: 1000,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Header.BodyLen = test.bodyLen
+
+			result := pkg.GetBodyLen()
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
+
+// TestDubboPackageGetLen tests GetLen method
+func TestDubboPackageGetLen(t *testing.T) {
+	tests := []struct {
+		desc     string
+		bodyLen  int
+		expected int
+	}{
+		{
+			desc:     "zero length body",
+			bodyLen:  0,
+			expected: 16, // HEADER_LENGTH = 16
+		},
+		{
+			desc:     "100 bytes body",
+			bodyLen:  100,
+			expected: 116, // 16 + 100
+		},
+		{
+			desc:     "1000 bytes body",
+			bodyLen:  1000,
+			expected: 1016, // 16 + 1000
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Header.BodyLen = test.bodyLen
+
+			result := pkg.GetLen()
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
+
+// TestDubboPackageGetBody tests GetBody method
+func TestDubboPackageGetBody(t *testing.T) {
+	tests := []struct {
+		desc     string
+		body     any
+		expected any
+	}{
+		{
+			desc:     "with string body",
+			body:     "test body",
+			expected: "test body",
+		},
+		{
+			desc:     "with integer body",
+			body:     42,
+			expected: 42,
+		},
+		{
+			desc:     "with map body",
+			body:     map[string]any{"key": "value"},
+			expected: map[string]any{"key": "value"},
+		},
+		{
+			desc:     "with nil body",
+			body:     nil,
+			expected: nil,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Body = test.body
+
+			result := pkg.GetBody()
+			assert.Equal(t, test.expected, result)
+		})
+	}
+}
+
+// TestDubboPackageSetBody tests SetBody method
+func TestDubboPackageSetBody(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+	testBody := "test body content"
+
+	pkg.SetBody(testBody)
+
+	assert.Equal(t, testBody, pkg.Body)
+	assert.Equal(t, testBody, pkg.GetBody())
+}
+
+// TestDubboPackageSetAndGetHeader tests SetHeader and GetHeader methods
+func TestDubboPackageSetAndGetHeader(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+	header := DubboHeader{
+		SerialID:       1,
+		Type:           PackageRequest,
+		ID:             12345,
+		BodyLen:        100,
+		ResponseStatus: 0,
+	}
+
+	pkg.SetHeader(header)
+
+	result := pkg.GetHeader()
+	assert.Equal(t, header, result)
+	assert.Equal(t, header.ID, result.ID)
+	assert.Equal(t, header.Type, result.Type)
+}
+
+// TestDubboPackageSetAndGetID tests SetID method
+func TestDubboPackageSetAndGetID(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+	testID := int64(999999)
+
+	pkg.SetID(testID)
+
+	assert.Equal(t, testID, pkg.Header.ID)
+	assert.Equal(t, testID, pkg.GetHeader().ID)
+}
+
+// TestDubboPackageSetAndGetService tests SetService and GetService methods
+func TestDubboPackageSetAndGetService(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+	service := Service{
+		Path:      "com.example.service",
+		Interface: "UserService",
+		Group:     "production",
+		Version:   "1.0.0",
+		Method:    "getUser",
+		Timeout:   5 * time.Second,
+	}
+
+	pkg.SetService(service)
+
+	result := pkg.GetService()
+	assert.Equal(t, service, result)
+	assert.Equal(t, "com.example.service", result.Path)
+	assert.Equal(t, "UserService", result.Interface)
+}
+
+// TestDubboPackageSetResponseStatus tests SetResponseStatus method
+func TestDubboPackageSetResponseStatus(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+	status := byte(20)
+
+	pkg.SetResponseStatus(status)
+
+	assert.Equal(t, status, pkg.Header.ResponseStatus)
+}
+
+// TestDubboPackageString tests String method
+func TestDubboPackageString(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+	pkg.Service.Path = "test.service"
+	pkg.Body = "test body"
+
+	result := pkg.String()
+
+	assert.NotEmpty(t, result)
+	assert.Contains(t, result, "HessianPackage")
+	assert.Contains(t, result, "test.service")
+}
+
+// TestDubboPackageSetSerializer tests SetSerializer method
+func TestDubboPackageSetSerializer(t *testing.T) {
+	pkg := NewDubboPackage(nil)
+	serializer := &HessianSerializer{}
+
+	// Should not panic
+	assert.NotPanics(t, func() {
+		pkg.SetSerializer(serializer)
+	})
+
+	assert.NotNil(t, pkg.Codec)
+}
diff --git a/protocol/dubbo/impl/request_test.go b/protocol/dubbo/impl/request_test.go
new file mode 100644
index 000000000..87017f7be
--- /dev/null
+++ b/protocol/dubbo/impl/request_test.go
@@ -0,0 +1,206 @@
+/*
+ * 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 impl
+
+import (
+	"testing"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+// TestNewRequestPayload tests creating a new RequestPayload with various inputs
+func TestNewRequestPayload(t *testing.T) {
+	tests := []struct {
+		desc              string
+		args              any
+		attachments       map[string]any
+		expectParams      any
+		expectAttachments map[string]any
+	}{
+		{
+			desc:              "with all parameters",
+			args:              "request args",
+			attachments:       map[string]any{"key": "value"},
+			expectParams:      "request args",
+			expectAttachments: map[string]any{"key": "value"},
+		},
+		{
+			desc:              "with nil attachments",
+			args:              "request args",
+			attachments:       nil,
+			expectParams:      "request args",
+			expectAttachments: make(map[string]any),
+		},
+		{
+			desc:              "with nil args",
+			args:              nil,
+			attachments:       map[string]any{"trace_id": "12345"},
+			expectParams:      nil,
+			expectAttachments: map[string]any{"trace_id": "12345"},
+		},
+		{
+			desc:              "with empty attachments",
+			args:              []string{"arg1", "arg2"},
+			attachments:       map[string]any{},
+			expectParams:      []string{"arg1", "arg2"},
+			expectAttachments: map[string]any{},
+		},
+		{
+			desc:              "with complex args",
+			args:              map[string]any{"user_id": 123, "name": "test"},
+			attachments:       map[string]any{"version": "1.0"},
+			expectParams:      map[string]any{"user_id": 123, "name": "test"},
+			expectAttachments: map[string]any{"version": "1.0"},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			payload := NewRequestPayload(test.args, test.attachments)
+
+			assert.NotNil(t, payload)
+			assert.Equal(t, test.expectParams, payload.Params)
+			assert.NotNil(t, payload.Attachments)
+			assert.Equal(t, test.expectAttachments, payload.Attachments)
+		})
+	}
+}
+
+// TestEnsureRequestPayload tests EnsureRequestPayload with various body types
+func TestEnsureRequestPayload(t *testing.T) {
+	tests := []struct {
+		desc         string
+		body         any
+		expectParams any
+		expectNotNil bool
+	}{
+		{
+			desc:         "with RequestPayload object",
+			body:         NewRequestPayload("args", map[string]any{"key": "value"}),
+			expectParams: "args",
+			expectNotNil: true,
+		},
+		{
+			desc:         "with string object",
+			body:         "string args",
+			expectParams: "string args",
+			expectNotNil: true,
+		},
+		{
+			desc:         "with integer object",
+			body:         42,
+			expectParams: 42,
+			expectNotNil: true,
+		},
+		{
+			desc:         "with slice object",
+			body:         []int{1, 2, 3},
+			expectParams: []int{1, 2, 3},
+			expectNotNil: true,
+		},
+		{
+			desc:         "with map object",
+			body:         map[string]any{"method": "login", "user": "admin"},
+			expectParams: map[string]any{"method": "login", "user": "admin"},
+			expectNotNil: true,
+		},
+		{
+			desc:         "with nil object",
+			body:         nil,
+			expectParams: nil,
+			expectNotNil: true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			payload := EnsureRequestPayload(test.body)
+
+			if test.expectNotNil {
+				assert.NotNil(t, payload)
+				assert.NotNil(t, payload.Attachments)
+			}
+			assert.Equal(t, test.expectParams, payload.Params)
+		})
+	}
+}
+
+// TestNewRequestPayloadNilAttachments tests that nil attachments are converted to empty map
+func TestNewRequestPayloadNilAttachments(t *testing.T) {
+	payload := NewRequestPayload("args", nil)
+
+	assert.NotNil(t, payload.Attachments)
+	assert.Equal(t, 0, len(payload.Attachments))
+}
+
+// TestRequestPayloadFields tests that RequestPayload fields are correctly set
+func TestRequestPayloadFields(t *testing.T) {
+	tests := []struct {
+		desc        string
+		args        any
+		attachments map[string]any
+	}{
+		{
+			desc:        "request with args and attachments",
+			args:        "user login",
+			attachments: map[string]any{"session": "xxx", "timestamp": 1234567890},
+		},
+		{
+			desc:        "request with only args",
+			args:        []any{"param1", "param2"},
+			attachments: map[string]any{},
+		},
+		{
+			desc:        "request with complex structure",
+			args:        map[string]any{"data": []int{1, 2, 3}},
+			attachments: map[string]any{"trace": "abc123", "span": "def456"},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			payload := NewRequestPayload(test.args, test.attachments)
+
+			assert.Equal(t, test.args, payload.Params)
+			assert.Equal(t, test.attachments, payload.Attachments)
+		})
+	}
+}
+
+// TestEnsureRequestPayloadWithRequestPayload tests EnsureRequestPayload returns the same RequestPayload
+func TestEnsureRequestPayloadWithRequestPayload(t *testing.T) {
+	original := NewRequestPayload("args data", map[string]any{"key": "value"})
+	result := EnsureRequestPayload(original)
+
+	assert.Equal(t, original, result)
+	assert.Equal(t, original.Params, result.Params)
+	assert.Equal(t, original.Attachments, result.Attachments)
+}
+
+// TestEnsureRequestPayloadCreateNewPayload tests EnsureRequestPayload creates new payload for non-RequestPayload objects
+func TestEnsureRequestPayloadCreateNewPayload(t *testing.T) {
+	testArgs := "test arguments"
+	payload := EnsureRequestPayload(testArgs)
+
+	assert.NotNil(t, payload)
+	assert.Equal(t, testArgs, payload.Params)
+	assert.NotNil(t, payload.Attachments)
+	assert.Equal(t, 0, len(payload.Attachments))
+}
diff --git a/protocol/dubbo/impl/response_test.go b/protocol/dubbo/impl/response_test.go
new file mode 100644
index 000000000..76ed20d93
--- /dev/null
+++ b/protocol/dubbo/impl/response_test.go
@@ -0,0 +1,219 @@
+/*
+ * 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 impl
+
+import (
+	"errors"
+	"testing"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+// TestNewResponsePayload tests creating a new ResponsePayload with various inputs
+func TestNewResponsePayload(t *testing.T) {
+	// Pre-define error variables to ensure consistent comparison
+	testError := errors.New("test error")
+	errorOccurred := errors.New("error occurred")
+
+	tests := []struct {
+		desc              string
+		rspObj            any
+		exception         error
+		attachments       map[string]any
+		expectRspObj      any
+		expectException   error
+		expectAttachments map[string]any
+	}{
+		{
+			desc:              "with all parameters",
+			rspObj:            "response data",
+			exception:         testError,
+			attachments:       map[string]any{"key": "value"},
+			expectRspObj:      "response data",
+			expectException:   testError,
+			expectAttachments: map[string]any{"key": "value"},
+		},
+		{
+			desc:              "with nil attachments",
+			rspObj:            "response data",
+			exception:         nil,
+			attachments:       nil,
+			expectRspObj:      "response data",
+			expectException:   nil,
+			expectAttachments: make(map[string]any),
+		},
+		{
+			desc:              "with nil rspObj and exception",
+			rspObj:            nil,
+			exception:         errorOccurred,
+			attachments:       map[string]any{"error_code": 500},
+			expectRspObj:      nil,
+			expectException:   errorOccurred,
+			expectAttachments: map[string]any{"error_code": 500},
+		},
+		{
+			desc:              "with empty attachments",
+			rspObj:            123,
+			exception:         nil,
+			attachments:       map[string]any{},
+			expectRspObj:      123,
+			expectException:   nil,
+			expectAttachments: map[string]any{},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			payload := NewResponsePayload(test.rspObj, test.exception, test.attachments)
+
+			assert.NotNil(t, payload)
+			assert.Equal(t, test.expectRspObj, payload.RspObj)
+			if test.expectException != nil {
+				assert.Error(t, payload.Exception)
+			} else {
+				assert.NoError(t, payload.Exception)
+			}
+			assert.NotNil(t, payload.Attachments)
+		})
+	}
+}
+
+// TestEnsureResponsePayload tests EnsureResponsePayload with various body types
+func TestEnsureResponsePayload(t *testing.T) {
+	tests := []struct {
+		desc              string
+		body              any
+		expectRspObj      any
+		expectException   error
+		expectAttachments map[string]any
+		expectNotNil      bool
+	}{
+		{
+			desc:            "with ResponsePayload object",
+			body:            NewResponsePayload("data", nil, map[string]any{"key": "value"}),
+			expectRspObj:    "data",
+			expectException: nil,
+			expectNotNil:    true,
+		},
+		{
+			desc:         "with error object",
+			body:         errors.New("test error"),
+			expectRspObj: nil,
+			expectNotNil: true,
+		},
+		{
+			desc:            "with string object",
+			body:            "string response",
+			expectRspObj:    "string response",
+			expectException: nil,
+			expectNotNil:    true,
+		},
+		{
+			desc:            "with integer object",
+			body:            42,
+			expectRspObj:    42,
+			expectException: nil,
+			expectNotNil:    true,
+		},
+		{
+			desc:            "with map object",
+			body:            map[string]any{"result": "success"},
+			expectRspObj:    map[string]any{"result": "success"},
+			expectException: nil,
+			expectNotNil:    true,
+		},
+		{
+			desc:            "with nil object",
+			body:            nil,
+			expectRspObj:    nil,
+			expectException: nil,
+			expectNotNil:    true,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			payload := EnsureResponsePayload(test.body)
+
+			if test.expectNotNil {
+				assert.NotNil(t, payload)
+				assert.NotNil(t, payload.Attachments)
+			}
+			assert.Equal(t, test.expectRspObj, payload.RspObj)
+		})
+	}
+}
+
+// TestNewResponsePayloadNilAttachments tests that nil attachments are converted to empty map
+func TestNewResponsePayloadNilAttachments(t *testing.T) {
+	payload := NewResponsePayload("response", nil, nil)
+
+	assert.NotNil(t, payload.Attachments)
+	assert.Equal(t, 0, len(payload.Attachments))
+}
+
+// TestResponsePayloadFields tests that ResponsePayload fields are correctly set
+func TestResponsePayloadFields(t *testing.T) {
+	tests := []struct {
+		desc        string
+		rspObj      any
+		exception   error
+		attachments map[string]any
+	}{
+		{
+			desc:        "response with data and attachments",
+			rspObj:      "user data",
+			exception:   nil,
+			attachments: map[string]any{"status": "ok", "code": 200},
+		},
+		{
+			desc:        "response with exception",
+			rspObj:      nil,
+			exception:   errors.New("service error"),
+			attachments: map[string]any{"error_id": "ERR_001"},
+		},
+		{
+			desc:        "response with only data",
+			rspObj:      []int{1, 2, 3},
+			exception:   nil,
+			attachments: map[string]any{},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			payload := NewResponsePayload(test.rspObj, test.exception, test.attachments)
+
+			assert.Equal(t, test.rspObj, payload.RspObj)
+			assert.Equal(t, test.exception, payload.Exception)
+			assert.Equal(t, test.attachments, payload.Attachments)
+		})
+	}
+}
+
+// TestEnsureResponsePayloadWithResponsePayload tests EnsureResponsePayload returns the same ResponsePayload
+func TestEnsureResponsePayloadWithResponsePayload(t *testing.T) {
+	original := NewResponsePayload("data", nil, map[string]any{"key": "value"})
+	result := EnsureResponsePayload(original)
+
+	assert.Equal(t, original, result)
+	assert.Equal(t, original.RspObj, result.RspObj)
+	assert.Equal(t, original.Attachments, result.Attachments)
+}
diff --git a/protocol/dubbo/impl/serialization_test.go b/protocol/dubbo/impl/serialization_test.go
new file mode 100644
index 000000000..ec95117e4
--- /dev/null
+++ b/protocol/dubbo/impl/serialization_test.go
@@ -0,0 +1,157 @@
+/*
+ * 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 impl
+
+import (
+	"testing"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+import (
+	"dubbo.apache.org/dubbo-go/v3/common/constant"
+)
+
+// TestGetSerializerById tests GetSerializerById with valid and invalid serializer IDs
+func TestGetSerializerById(t *testing.T) {
+	// Setup: Create a mock serializer for testing
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	tests := []struct {
+		desc        string
+		id          byte
+		shouldPanic bool
+	}{
+		{
+			desc:        "valid Hessian2 serializer ID",
+			id:          constant.SHessian2,
+			shouldPanic: false,
+		},
+		{
+			desc:        "valid Protobuf serializer ID",
+			id:          constant.SProto,
+			shouldPanic: true, // Will panic because serializer is not registered
+		},
+		{
+			desc:        "invalid serializer ID 255",
+			id:          255,
+			shouldPanic: true, // Will panic because ID is not in nameMaps
+		},
+		{
+			desc:        "default Hessian2 serializer ID 0",
+			id:          0,
+			shouldPanic: true, // Will panic because ID 0 is not registered in nameMaps
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			if test.shouldPanic {
+				assert.Panics(t, func() {
+					GetSerializerById(test.id)
+				})
+			} else {
+				assert.NotPanics(t, func() {
+					serializer, err := GetSerializerById(test.id)
+					assert.NoError(t, err)
+					assert.NotNil(t, serializer)
+					assert.Equal(t, mockSerializer, serializer)
+				})
+			}
+		})
+	}
+}
+
+// TestGetSerializerByIdConsistency tests that GetSerializerById returns consistent results
+func TestGetSerializerByIdConsistency(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	// Call multiple times, should get same result
+	result1, err1 := GetSerializerById(constant.SHessian2)
+	result2, err2 := GetSerializerById(constant.SHessian2)
+	result3, err3 := GetSerializerById(constant.SHessian2)
+
+	assert.NoError(t, err1)
+	assert.NoError(t, err2)
+	assert.NoError(t, err3)
+	assert.Equal(t, result1, result2)
+	assert.Equal(t, result2, result3)
+}
+
+// TestSetSerializer tests SetSerializer can register a serializer
+func TestSetSerializer(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+
+	// SetSerializer should not panic
+	assert.NotPanics(t, func() {
+		SetSerializer(constant.Hessian2Serialization, mockSerializer)
+	})
+
+	// After setting, GetSerializerById should return the same serializer
+	result, err := GetSerializerById(constant.SHessian2)
+	assert.NoError(t, err)
+	assert.Equal(t, mockSerializer, result)
+}
+
+// TestSetSerializerReplaces tests that SetSerializer can replace an existing serializer
+func TestSetSerializerReplaces(t *testing.T) {
+	mockSerializer1 := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer1)
+
+	result1, _ := GetSerializerById(constant.SHessian2)
+	assert.Equal(t, mockSerializer1, result1)
+
+	// Replace with a new serializer
+	mockSerializer2 := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer2)
+
+	result2, _ := GetSerializerById(constant.SHessian2)
+	assert.Equal(t, mockSerializer2, result2)
+}
+
+// TestSetSerializerWithMultipleNames tests SetSerializer with different serialization names
+func TestSetSerializerWithMultipleNames(t *testing.T) {
+	hessianSerializer := &HessianSerializer{}
+
+	// Register the same serializer with multiple names
+	SetSerializer(constant.Hessian2Serialization, hessianSerializer)
+
+	// Verify it's registered
+	result, err := GetSerializerById(constant.SHessian2)
+	assert.NoError(t, err)
+	assert.Equal(t, hessianSerializer, result)
+}
+
+// TestSetSerializerNotNil tests SetSerializer with non-nil serializer
+func TestSetSerializerNotNil(t *testing.T) {
+	serializer := &HessianSerializer{}
+
+	// SetSerializer should accept non-nil serializer
+	assert.NotPanics(t, func() {
+		SetSerializer(constant.Hessian2Serialization, serializer)
+	})
+
+	// Verify the serializer is set correctly
+	result, err := GetSerializerById(constant.SHessian2)
+	assert.NoError(t, err)
+	assert.NotNil(t, result)
+}
diff --git a/protocol/dubbo/impl/serialize_test.go b/protocol/dubbo/impl/serialize_test.go
new file mode 100644
index 000000000..12a21264e
--- /dev/null
+++ b/protocol/dubbo/impl/serialize_test.go
@@ -0,0 +1,486 @@
+/*
+ * 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 impl
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+)
+
+import (
+	"github.com/stretchr/testify/assert"
+)
+
+import (
+	"dubbo.apache.org/dubbo-go/v3/common/constant"
+)
+
+// TestLoadSerializerWithDefaultHessian2 tests LoadSerializer with default Hessian2 serialization
+func TestLoadSerializerWithDefaultHessian2(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = 0 // Default SerialID
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+	assert.NotNil(t, pkg.Codec)
+}
+
+// TestLoadSerializerWithHessian2 tests LoadSerializer with explicit Hessian2 serialization
+func TestLoadSerializerWithHessian2(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = constant.SHessian2
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+	assert.NotNil(t, pkg.Codec)
+}
+
+// TestLoadSerializerWithDifferentValidID tests LoadSerializer with different valid serializer ID
+func TestLoadSerializerWithDifferentValidID(t *testing.T) {
+	mockHessianSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockHessianSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = constant.SHessian2
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+	assert.NotNil(t, pkg.Codec)
+}
+
+// TestLoadSerializerWithInvalidID tests LoadSerializer with invalid serializer ID panics
+func TestLoadSerializerWithInvalidID(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = 255 // Invalid serializer ID
+
+	assert.Panics(t, func() {
+		LoadSerializer(pkg)
+	})
+}
+
+// TestLoadSerializerWithZeroIDDefaultsToHessian2 tests that SerialID 0 defaults to Hessian2
+func TestLoadSerializerWithZeroIDDefaultsToHessian2(t *testing.T) {
+	mockHessianSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockHessianSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = 0
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+	// Verify that the loaded serializer is for Hessian2
+	assert.NotNil(t, pkg.Codec)
+}
+
+// TestLoadSerializerWithNilPackage tests LoadSerializer handles package correctly
+func TestLoadSerializerWithNilPackage(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = constant.SHessian2
+
+	assert.NotPanics(t, func() {
+		err := LoadSerializer(pkg)
+		assert.NoError(t, err)
+	})
+}
+
+// TestLoadSerializerMultipleInstances tests that LoadSerializer works with multiple packages
+func TestLoadSerializerMultipleInstances(t *testing.T) {
+	mockHessianSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockHessianSerializer)
+
+	pkg1 := NewDubboPackage(nil)
+	pkg1.Header.SerialID = constant.SHessian2
+
+	pkg2 := NewDubboPackage(nil)
+	pkg2.Header.SerialID = 0 // Default to Hessian2
+
+	err1 := LoadSerializer(pkg1)
+	err2 := LoadSerializer(pkg2)
+
+	assert.NoError(t, err1)
+	assert.NoError(t, err2)
+	assert.NotNil(t, pkg1.Codec)
+	assert.NotNil(t, pkg2.Codec)
+}
+
+// TestLoadSerializerWithBufferedData tests LoadSerializer with buffered data in package
+func TestLoadSerializerWithBufferedData(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	data := bytes.NewBuffer([]byte{0x01, 0x02, 0x03})
+	pkg := NewDubboPackage(data)
+	pkg.Header.SerialID = constant.SHessian2
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+	assert.NotNil(t, pkg.Codec)
+}
+
+// TestLoadSerializerDoesNotPanicWithValidID tests LoadSerializer doesn't panic with valid IDs
+func TestLoadSerializerDoesNotPanicWithValidID(t *testing.T) {
+	mockHessianSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockHessianSerializer)
+
+	tests := []struct {
+		desc       string
+		serialID   byte
+		shouldFail bool
+	}{
+		{
+			desc:       "default Hessian2 (0)",
+			serialID:   0,
+			shouldFail: false,
+		},
+		{
+			desc:       "explicit Hessian2",
+			serialID:   constant.SHessian2,
+			shouldFail: false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Header.SerialID = test.serialID
+
+			if test.shouldFail {
+				assert.Panics(t, func() {
+					LoadSerializer(pkg)
+				})
+			} else {
+				assert.NotPanics(t, func() {
+					err := LoadSerializer(pkg)
+					assert.NoError(t, err)
+				})
+			}
+		})
+	}
+}
+
+// TestLoadSerializerSetsSerializerInCodec tests that LoadSerializer properly sets the serializer in the codec
+func TestLoadSerializerSetsSerializerInCodec(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = constant.SHessian2
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+	assert.NotNil(t, pkg.Codec)
+	assert.NotNil(t, pkg.Codec.serializer)
+}
+
+// TestSerializerInterface tests that Serializer interface is properly defined
+func TestSerializerInterface(t *testing.T) {
+	// Verify that HessianSerializer implements Serializer interface
+	var _ Serializer = (*HessianSerializer)(nil)
+
+	mockSerializer := &HessianSerializer{}
+	assert.NotNil(t, mockSerializer)
+}
+
+// TestLoadSerializerConsistency tests that LoadSerializer gives consistent results for same input
+func TestLoadSerializerConsistency(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg1 := NewDubboPackage(nil)
+	pkg1.Header.SerialID = constant.SHessian2
+
+	pkg2 := NewDubboPackage(nil)
+	pkg2.Header.SerialID = constant.SHessian2
+
+	err1 := LoadSerializer(pkg1)
+	err2 := LoadSerializer(pkg2)
+
+	assert.NoError(t, err1)
+	assert.NoError(t, err2)
+	assert.Equal(t, err1, err2)
+}
+
+// TestLoadSerializerReplacesExistingSerializer tests that LoadSerializer can replace existing serializer
+func TestLoadSerializerReplacesExistingSerializer(t *testing.T) {
+	mockSerializer1 := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer1)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = constant.SHessian2
+
+	err1 := LoadSerializer(pkg)
+	assert.NoError(t, err1)
+
+	// Create a new mock serializer and replace
+	mockSerializer2 := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer2)
+
+	err2 := LoadSerializer(pkg)
+	assert.NoError(t, err2)
+}
+
+// TestLoadSerializerWithAllBytesValues tests LoadSerializer with various byte values
+func TestLoadSerializerWithAllBytesValues(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	validValues := []byte{
+		0,                  // Default - should map to Hessian2
+		constant.SHessian2, // Explicit Hessian2
+	}
+
+	for _, byteVal := range validValues {
+		t.Run(fmt.Sprintf("serial_id_%d", byteVal), func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Header.SerialID = byteVal
+
+			if byteVal == 0 || byteVal == constant.SHessian2 {
+				err := LoadSerializer(pkg)
+				assert.NoError(t, err)
+				assert.NotNil(t, pkg.Codec)
+			}
+		})
+	}
+}
+
+// TestLoadSerializerWithInvalidByteValues tests that invalid byte values panic
+func TestLoadSerializerWithInvalidByteValues(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	// Use a known invalid value that should not be registered as a serializer ID.
+	invalidValues := []byte{255}
+
+	for _, byteVal := range invalidValues {
+		t.Run(fmt.Sprintf("invalid_serial_id_%d", byteVal), func(t *testing.T) {
+			pkg := NewDubboPackage(nil)
+			pkg.Header.SerialID = byteVal
+
+			assert.Panics(t, func() {
+				LoadSerializer(pkg)
+			})
+		})
+	}
+}
+
+// TestLoadSerializerErrorHandling tests error handling in LoadSerializer
+func TestLoadSerializerErrorHandling(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = constant.SHessian2
+
+	// Should not raise error with valid setup
+	assert.NotPanics(t, func() {
+		err := LoadSerializer(pkg)
+		assert.NoError(t, err)
+	})
+}
+
+// TestLoadSerializerCodecIsNotNil tests that Codec is properly initialized
+func TestLoadSerializerCodecIsNotNil(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = constant.SHessian2
+
+	// Before LoadSerializer, Codec should not be nil (created by NewDubboPackage)
+	assert.NotNil(t, pkg.Codec)
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+
+	// After LoadSerializer, Codec should still exist
+	assert.NotNil(t, pkg.Codec)
+}
+
+// TestLoadSerializerWithHeaderData tests LoadSerializer properly uses Header.SerialID
+func TestLoadSerializerWithHeaderData(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	// Explicitly set Header fields
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 12345
+	pkg.Header.Type = PackageRequest
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+	assert.Equal(t, constant.SHessian2, pkg.Header.SerialID)
+	assert.Equal(t, int64(12345), pkg.Header.ID)
+}
+
+// TestLoadSerializerSequentialCalls tests multiple sequential LoadSerializer calls
+func TestLoadSerializerSequentialCalls(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	for i := 0; i < 5; i++ {
+		pkg := NewDubboPackage(nil)
+		pkg.Header.SerialID = constant.SHessian2
+		pkg.Header.ID = int64(i)
+
+		err := LoadSerializer(pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, pkg.Codec)
+	}
+}
+
+// TestLoadSerializerWithDataBuffer tests LoadSerializer with data buffer
+func TestLoadSerializerWithDataBuffer(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	testData := []byte{0xDA, 0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+	data := bytes.NewBuffer(testData)
+	pkg := NewDubboPackage(data)
+	pkg.Header.SerialID = constant.SHessian2
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+	assert.NotNil(t, pkg.Codec)
+}
+
+// TestHessianSerializerMarshalRequest tests Hessian serializer marshal for request
+func TestHessianSerializerMarshalRequest(t *testing.T) {
+	serializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, serializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Body = []any{"test"}
+	pkg.Header.Type = PackageRequest
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 12345
+	pkg.Service.Interface = "TestInterface"
+	pkg.Service.Path = "test.path"
+	pkg.Service.Method = "testMethod"
+	pkg.SetSerializer(serializer)
+
+	data, err := pkg.Marshal()
+	assert.NoError(t, err)
+	assert.NotNil(t, data)
+	assert.Greater(t, data.Len(), 0)
+}
+
+// TestHessianSerializerMarshalResponse tests Hessian serializer marshal for response
+func TestHessianSerializerMarshalResponse(t *testing.T) {
+	serializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, serializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Body = "response data"
+	pkg.Header.Type = PackageResponse
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 54321
+	pkg.Header.ResponseStatus = Response_OK
+	pkg.SetSerializer(serializer)
+
+	data, err := pkg.Marshal()
+	assert.NoError(t, err)
+	assert.NotNil(t, data)
+	assert.Greater(t, data.Len(), 0)
+}
+
+// TestHessianSerializerMarshalResponseWithException tests Hessian marshaling for exception response
+func TestHessianSerializerMarshalResponseWithException(t *testing.T) {
+	serializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, serializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Body = []any{} // Empty body for exception response
+	pkg.Header.Type = PackageResponse
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 99999
+	pkg.Header.ResponseStatus = Response_SERVICE_ERROR
+	pkg.SetSerializer(serializer)
+
+	data, err := pkg.Marshal()
+	assert.NoError(t, err)
+	assert.NotNil(t, data)
+}
+
+// TestHessianSerializerMarshalHeartbeat tests Hessian serializer marshal for heartbeat
+func TestHessianSerializerMarshalHeartbeat(t *testing.T) {
+	serializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, serializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Body = []any{}
+	pkg.Header.Type = PackageHeartbeat
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.ID = 77777
+	pkg.SetSerializer(serializer)
+
+	data, err := pkg.Marshal()
+	assert.NoError(t, err)
+	assert.NotNil(t, data)
+	assert.Greater(t, data.Len(), 0)
+}
+
+// TestLoadSerializerWithMultipleCalls tests LoadSerializer consistency
+func TestLoadSerializerWithMultipleCalls(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	// Call LoadSerializer multiple times
+	for i := 0; i < 5; i++ {
+		pkg := NewDubboPackage(nil)
+		pkg.Header.SerialID = constant.SHessian2
+
+		err := LoadSerializer(pkg)
+		assert.NoError(t, err)
+		assert.NotNil(t, pkg.Codec.serializer)
+	}
+}
+
+// TestLoadSerializerPackageInheritance tests that loaded serializer persists in package
+func TestLoadSerializerPackageInheritance(t *testing.T) {
+	mockSerializer := &HessianSerializer{}
+	SetSerializer(constant.Hessian2Serialization, mockSerializer)
+
+	pkg := NewDubboPackage(nil)
+	pkg.Header.SerialID = constant.SHessian2
+	pkg.Header.Type = PackageRequest
+	pkg.Header.ID = 55555
+	pkg.Service.Interface = "TestInterface"
+	pkg.Body = []any{"test"}
+
+	err := LoadSerializer(pkg)
+	assert.NoError(t, err)
+
+	// Verify serializer is accessible for marshaling
+	data, err := pkg.Marshal()
+	assert.NoError(t, err)
+	assert.NotNil(t, data)
+}
diff --git a/protocol/dubbo/opentracing_test.go b/protocol/dubbo/opentracing_test.go
new file mode 100644
index 000000000..35319bdbf
--- /dev/null
+++ b/protocol/dubbo/opentracing_test.go
@@ -0,0 +1,275 @@
+/*
+ * 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 dubbo
+
+import (
+	"testing"
+)
+
+import (
+	"github.com/opentracing/opentracing-go"
+	"github.com/opentracing/opentracing-go/mocktracer"
+
+	"github.com/stretchr/testify/assert"
+)
+
+import (
+	"dubbo.apache.org/dubbo-go/v3/common/constant"
+	"dubbo.apache.org/dubbo-go/v3/protocol/invocation"
+)
+
+// TestFilterContext tests the filterContext function
+func TestFilterContext(t *testing.T) {
+	tests := []struct {
+		desc               string
+		attachments        map[string]any
+		expectedLen        int
+		expectedContains   map[string]string
+		notExpectedContain []string
+	}{
+		{
+			desc:               "empty attachments",
+			attachments:        make(map[string]any),
+			expectedLen:        0,
+			expectedContains:   map[string]string{},
+			notExpectedContain: []string{},
+		},
+		{
+			desc: "only string values",
+			attachments: map[string]any{
+				"key1": "value1",
+				"key2": "value2",
+				"key3": "value3",
+			},
+			expectedLen: 3,
+			expectedContains: map[string]string{
+				"key1": "value1",
+				"key2": "value2",
+				"key3": "value3",
+			},
+			notExpectedContain: []string{},
+		},
+		{
+			desc: "mixed types",
+			attachments: map[string]any{
+				"stringKey":        "stringValue",
+				"intKey":           123,
+				"boolKey":          true,
+				"anotherStringKey": "anotherValue",
+			},
+			expectedLen: 2,
+			expectedContains: map[string]string{
+				"stringKey":        "stringValue",
+				"anotherStringKey": "anotherValue",
+			},
+			notExpectedContain: []string{"intKey", "boolKey"},
+		},
+		{
+			desc: "with nil values",
+			attachments: map[string]any{
+				"stringKey": "stringValue",
+				"nilKey":    nil,
+				"intKey":    456,
+			},
+			expectedLen: 1,
+			expectedContains: map[string]string{
+				"stringKey": "stringValue",
+			},
+			notExpectedContain: []string{"nilKey", "intKey"},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			result := filterContext(test.attachments)
+			assert.Equal(t, test.expectedLen, len(result))
+			for k, v := range test.expectedContains {
+				assert.Equal(t, v, result[k])
+			}
+			for _, k := range test.notExpectedContain {
+				assert.NotContains(t, result, k)
+			}
+		})
+	}
+}
+
+// TestFillTraceAttachments tests the fillTraceAttachments function
+func TestFillTraceAttachments(t *testing.T) {
+	tests := []struct {
+		desc                string
+		initialAttachments  map[string]any
+		traceAttachment     map[string]string
+		expectedAttachments map[string]any
+	}{
+		{
+			desc:               "filling empty attachments",
+			initialAttachments: make(map[string]any),
+			traceAttachment: map[string]string{
+				"trace.key1": "trace.value1",
+				"trace.key2": "trace.value2",
+			},
+			expectedAttachments: map[string]any{
+				"trace.key1": "trace.value1",
+				"trace.key2": "trace.value2",
+			},
+		},
+		{
+			desc: "filling attachments with existing values",
+			initialAttachments: map[string]any{
+				"existing": "value",
+			},
+			traceAttachment: map[string]string{
+				"trace.key1": "trace.value1",
+			},
+			expectedAttachments: map[string]any{
+				"existing":   "value",
+				"trace.key1": "trace.value1",
+			},
+		},
+		{
+			desc: "with empty trace attachments",
+			initialAttachments: map[string]any{
+				"key": "value",
+			},
+			traceAttachment: make(map[string]string),
+			expectedAttachments: map[string]any{
+				"key": "value",
+			},
+		},
+		{
+			desc: "overwriting existing keys",
+			initialAttachments: map[string]any{
+				"key": "oldValue",
+			},
+			traceAttachment: map[string]string{
+				"key": "newValue",
+			},
+			expectedAttachments: map[string]any{
+				"key": "newValue",
+			},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			fillTraceAttachments(test.initialAttachments, test.traceAttachment)
+			assert.Equal(t, len(test.expectedAttachments), len(test.initialAttachments))
+			for k, v := range test.expectedAttachments {
+				assert.Equal(t, v, test.initialAttachments[k])
+			}
+		})
+	}
+}
+
+// TestInjectTraceCtx tests the injectTraceCtx function
+func TestInjectTraceCtx(t *testing.T) {
+	opentracing.SetGlobalTracer(mocktracer.New())
+
+	tests := []struct {
+		desc        string
+		attachments map[string]any
+		expectError bool
+	}{
+		{
+			desc:        "with empty attachments",
+			attachments: make(map[string]any),
+			expectError: false,
+		},
+		{
+			desc: "with existing string attachments",
+			attachments: map[string]any{
+				constant.VersionKey: "1.0",
+				constant.GroupKey:   "testGroup",
+			},
+			expectError: false,
+		},
+		{
+			desc: "with mixed type attachments",
+			attachments: map[string]any{
+				"stringKey": "stringValue",
+				"intKey":    123,
+				"boolKey":   true,
+			},
+			expectError: false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			inv := invocation.NewRPCInvocation("testMethod", []any{}, test.attachments)
+			span := opentracing.StartSpan("test-span")
+			err := injectTraceCtx(span, inv)
+			span.Finish()
+
+			if test.expectError {
+				assert.Error(t, err)
+			} else {
+				assert.NoError(t, err)
+				assert.NotNil(t, inv.Attachments())
+			}
+		})
+	}
+}
+
+// TestInjectTraceCtxIntegration tests the complete flow of filtering and filling trace attachments
+func TestInjectTraceCtxIntegration(t *testing.T) {
+	mockTracer := mocktracer.New()
+	opentracing.SetGlobalTracer(mockTracer)
+
+	tests := []struct {
+		desc        string
+		attachments map[string]any
+		methods     []any
+	}{
+		{
+			desc: "with version and group",
+			attachments: map[string]any{
+				constant.VersionKey: "1.0.0",
+				constant.GroupKey:   "myGroup",
+				"customKey":         "customValue",
+			},
+			methods: []any{"arg1", "arg2"},
+		},
+		{
+			desc: "with minimal attachments",
+			attachments: map[string]any{
+				constant.VersionKey: "1.0",
+			},
+			methods: []any{},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.desc, func(t *testing.T) {
+			inv := invocation.NewRPCInvocation("myMethod", test.methods, test.attachments)
+
+			span := opentracing.StartSpan("test-operation")
+			err := injectTraceCtx(span, inv)
+			span.Finish()
+
+			assert.NoError(t, err)
+			finalAttachments := inv.Attachments()
+			assert.NotNil(t, finalAttachments)
+
+			// Verify original attachments are preserved
+			for k, v := range test.attachments {
+				assert.Equal(t, v, finalAttachments[k])
+			}
+		})
+	}
+}