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 <[email protected]>
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])
+                       }
+               })
+       }
+}


Reply via email to