You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2023/05/09 14:41:38 UTC

[plc4x] 02/02: test(plc4go/spi): replace temp mocks with mockery mock

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

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 3a5ccfac1b3c793aca8b766f185cf8e4c9243c17
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Tue May 9 15:37:08 2023 +0200

    test(plc4go/spi): replace temp mocks with mockery mock
---
 plc4go/internal/bacnetip/Connection.go             |   4 +-
 plc4go/internal/cbus/Discoverer_test.go            |   2 +-
 plc4go/internal/cbus/Writer_test.go                |   4 +-
 plc4go/spi/default/DefaultBrowser.go               |   6 +
 plc4go/spi/default/DefaultBrowser_test.go          |  27 +-
 plc4go/spi/default/DefaultCodec.go                 |   2 +-
 plc4go/spi/default/DefaultCodec_test.go            | 157 +++---
 plc4go/spi/default/DefaultConnection_test.go       | 123 ++++-
 plc4go/spi/default/DefaultDriver_test.go           |  77 ++-
 plc4go/spi/default/mock_MessageCodec_test.go       | 447 ++++++++++++++++
 plc4go/spi/default/mock_Message_test.go            | 237 +++++++++
 .../mock_PlcConnectionConnectResult_test.go        | 139 +++++
 plc4go/spi/default/mock_PlcConnection_test.go      | 563 +++++++++++++++++++++
 plc4go/spi/default/mock_PlcQuery_test.go           |  93 ++++
 plc4go/spi/default/mock_PlcTagHandler_test.go      | 163 ++++++
 plc4go/spi/default/mock_TransportInstance_test.go  | 506 ++++++++++++++++++
 .../{testDriver_test.go => mock_requirements.go}   |  43 +-
 plc4go/spi/default/testBrowser_test.go             |  39 --
 plc4go/spi/default/testConnection_test.go          |  99 ----
 plc4go/spi/default/testMessageCodec_test.go        |  93 ----
 plc4go/spi/default/testMessage_test.go             |  49 --
 plc4go/spi/default/testQuery_test.go               |  28 -
 plc4go/spi/default/testTagHandler_test.go          |  34 --
 plc4go/spi/transports/TransportInstance.go         |   2 +-
 plc4go/spi/utils/Net.go                            |   6 +-
 25 files changed, 2458 insertions(+), 485 deletions(-)

diff --git a/plc4go/internal/bacnetip/Connection.go b/plc4go/internal/bacnetip/Connection.go
index 7354d61fe3..0258615506 100644
--- a/plc4go/internal/bacnetip/Connection.go
+++ b/plc4go/internal/bacnetip/Connection.go
@@ -22,6 +22,7 @@ package bacnetip
 import (
 	"context"
 	"fmt"
+	"github.com/apache/plc4x/plc4go/spi/utils"
 	"sync"
 	"time"
 
@@ -30,7 +31,6 @@ import (
 	"github.com/apache/plc4x/plc4go/spi"
 	"github.com/apache/plc4x/plc4go/spi/default"
 	internalModel "github.com/apache/plc4x/plc4go/spi/model"
-	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/rs/zerolog/log"
 )
 
@@ -85,11 +85,11 @@ func (c *Connection) ConnectWithContext(ctx context.Context) <-chan plc4go.PlcCo
 				log.Trace().Msg("Polling data")
 				incomingMessageChannel := c.messageCodec.GetDefaultIncomingMessageChannel()
 				timeout := time.NewTimer(20 * time.Millisecond)
+				defer utils.CleanupTimer(timeout)
 				select {
 				case message := <-incomingMessageChannel:
 					// TODO: implement mapping to subscribers
 					log.Info().Msgf("Received \n%v", message)
-					utils.CleanupTimer(timeout)
 				case <-timeout.C:
 				}
 			}
diff --git a/plc4go/internal/cbus/Discoverer_test.go b/plc4go/internal/cbus/Discoverer_test.go
index 2e6ecffac5..8c7949d1fc 100644
--- a/plc4go/internal/cbus/Discoverer_test.go
+++ b/plc4go/internal/cbus/Discoverer_test.go
@@ -290,7 +290,7 @@ func TestDiscoverer_createTransportInstanceDispatcher(t *testing.T) {
 			assert.NotNilf(t, dispatcher, "createTransportInstanceDispatcher(%v, %v, %v, %v, %v)", tt.args.ctx, tt.args.wg, tt.args.ip, tt.args.tcpTransport, tt.args.transportInstances)
 			dispatcher()
 			timeout := time.NewTimer(2 * time.Second)
-			utils.CleanupTimer(timeout)
+			defer utils.CleanupTimer(timeout)
 			select {
 			case <-timeout.C:
 				t.Error("timeout")
diff --git a/plc4go/internal/cbus/Writer_test.go b/plc4go/internal/cbus/Writer_test.go
index 4f592912fd..b1ba9db6cf 100644
--- a/plc4go/internal/cbus/Writer_test.go
+++ b/plc4go/internal/cbus/Writer_test.go
@@ -82,7 +82,7 @@ func TestWriter_Write(t *testing.T) {
 			},
 			wantAsserter: func(t *testing.T, results <-chan apiModel.PlcWriteRequestResult) bool {
 				timeout := time.NewTimer(2 * time.Second)
-				utils.CleanupTimer(timeout)
+				defer utils.CleanupTimer(timeout)
 				select {
 				case <-timeout.C:
 					t.Error("timeout")
@@ -104,7 +104,7 @@ func TestWriter_Write(t *testing.T) {
 			},
 			wantAsserter: func(t *testing.T, results <-chan apiModel.PlcWriteRequestResult) bool {
 				timeout := time.NewTimer(2 * time.Second)
-				utils.CleanupTimer(timeout)
+				defer utils.CleanupTimer(timeout)
 				select {
 				case <-timeout.C:
 					t.Fatal("timeout")
diff --git a/plc4go/spi/default/DefaultBrowser.go b/plc4go/spi/default/DefaultBrowser.go
index b9bc5532de..ab7a628f48 100644
--- a/plc4go/spi/default/DefaultBrowser.go
+++ b/plc4go/spi/default/DefaultBrowser.go
@@ -21,6 +21,7 @@ package _default
 
 import (
 	"context"
+	"github.com/rs/zerolog/log"
 
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
 	"github.com/apache/plc4x/plc4go/spi"
@@ -67,6 +68,11 @@ func (m *defaultBrowser) Browse(ctx context.Context, browseRequest apiModel.PlcB
 func (m *defaultBrowser) BrowseWithInterceptor(ctx context.Context, browseRequest apiModel.PlcBrowseRequest, interceptor func(result apiModel.PlcBrowseItem) bool) <-chan apiModel.PlcBrowseRequestResult {
 	result := make(chan apiModel.PlcBrowseRequestResult)
 	go func() {
+		defer func() {
+			if err := recover(); err != nil {
+				log.Error().Interface("err", err).Msg("caught panic")
+			}
+		}()
 		responseCodes := map[string]apiModel.PlcResponseCode{}
 		results := map[string][]apiModel.PlcBrowseItem{}
 		for _, queryName := range browseRequest.GetQueryNames() {
diff --git a/plc4go/spi/default/DefaultBrowser_test.go b/plc4go/spi/default/DefaultBrowser_test.go
index 5edb5e07a1..f7e45e1bd5 100644
--- a/plc4go/spi/default/DefaultBrowser_test.go
+++ b/plc4go/spi/default/DefaultBrowser_test.go
@@ -24,6 +24,7 @@ import (
 	spiModel "github.com/apache/plc4x/plc4go/spi/model"
 	"github.com/apache/plc4x/plc4go/spi/utils"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
 	"testing"
 	"time"
 
@@ -75,7 +76,7 @@ func Test_defaultBrowser_Browse(t *testing.T) {
 			},
 			wantAsserter: func(t *testing.T, results <-chan apiModel.PlcBrowseRequestResult) bool {
 				timeout := time.NewTimer(2 * time.Second)
-				utils.CleanupTimer(timeout)
+				defer utils.CleanupTimer(timeout)
 				select {
 				case result := <-results:
 					assert.NotNil(t, result)
@@ -110,6 +111,7 @@ func Test_defaultBrowser_BrowseWithInterceptor(t *testing.T) {
 		name         string
 		fields       fields
 		args         args
+		mockSetup    func(t *testing.T, fields *fields, args *args)
 		wantAsserter func(t *testing.T, results <-chan apiModel.PlcBrowseRequestResult) bool
 	}{
 		{
@@ -120,7 +122,7 @@ func Test_defaultBrowser_BrowseWithInterceptor(t *testing.T) {
 			},
 			wantAsserter: func(t *testing.T, results <-chan apiModel.PlcBrowseRequestResult) bool {
 				timeout := time.NewTimer(2 * time.Second)
-				utils.CleanupTimer(timeout)
+				defer utils.CleanupTimer(timeout)
 				select {
 				case result := <-results:
 					assert.NotNil(t, result)
@@ -133,22 +135,28 @@ func Test_defaultBrowser_BrowseWithInterceptor(t *testing.T) {
 		},
 		{
 			name: "Browse something",
-			fields: fields{
-				DefaultBrowserRequirements: testBrowser{},
-			},
 			args: args{
-				ctx: context.Background(),
+				ctx: func() context.Context {
+					timeout, cancelFunc := context.WithTimeout(context.Background(), 1*time.Second)
+					t.Cleanup(cancelFunc)
+					return timeout
+				}(),
 				browseRequest: spiModel.NewDefaultPlcBrowseRequest(
 					map[string]apiModel.PlcQuery{
-						"test": testQuery{},
+						"test": NewMockPlcQuery(t),
 					},
 					[]string{"test"},
 					nil,
 				),
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultBrowserRequirements(t)
+				requirements.EXPECT().BrowseQuery(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(0, nil)
+				fields.DefaultBrowserRequirements = requirements
+			},
 			wantAsserter: func(t *testing.T, results <-chan apiModel.PlcBrowseRequestResult) bool {
 				timeout := time.NewTimer(2 * time.Second)
-				utils.CleanupTimer(timeout)
+				defer utils.CleanupTimer(timeout)
 				select {
 				case result := <-results:
 					assert.NotNil(t, result)
@@ -162,6 +170,9 @@ func Test_defaultBrowser_BrowseWithInterceptor(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields, &tt.args)
+			}
 			m := &defaultBrowser{
 				DefaultBrowserRequirements: tt.fields.DefaultBrowserRequirements,
 			}
diff --git a/plc4go/spi/default/DefaultCodec.go b/plc4go/spi/default/DefaultCodec.go
index 8160e7eb23..5cf97068e6 100644
--- a/plc4go/spi/default/DefaultCodec.go
+++ b/plc4go/spi/default/DefaultCodec.go
@@ -332,13 +332,13 @@ mainLoop:
 		if !messageHandled {
 			workerLog.Trace().Msg("Message was not handled")
 			timeout := time.NewTimer(time.Millisecond * 40)
+			defer utils.CleanupTimer(timeout)
 			select {
 			case m.defaultIncomingMessageChannel <- message:
 			case <-timeout.C:
 				timeout.Stop()
 				workerLog.Warn().Msgf("Message discarded\n%s", message)
 			}
-			utils.CleanupTimer(timeout)
 		}
 	}
 }
diff --git a/plc4go/spi/default/DefaultCodec_test.go b/plc4go/spi/default/DefaultCodec_test.go
index c9014d7c4c..4dfb7f3305 100644
--- a/plc4go/spi/default/DefaultCodec_test.go
+++ b/plc4go/spi/default/DefaultCodec_test.go
@@ -27,6 +27,7 @@ import (
 	"github.com/apache/plc4x/plc4go/spi/transports"
 	"github.com/pkg/errors"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
 	"testing"
 	"time"
 )
@@ -335,7 +336,11 @@ func Test_defaultCodec_Connect(t *testing.T) {
 		{
 			name: "connect it",
 			fields: fields{
-				transportInstance: testTransportInstance{},
+				transportInstance: func() transports.TransportInstance {
+					instance := NewMockTransportInstance(t)
+					instance.EXPECT().IsConnected().Return(true)
+					return instance
+				}(),
 			},
 			wantErr: assert.NoError,
 		},
@@ -368,41 +373,47 @@ func Test_defaultCodec_ConnectWithContext(t *testing.T) {
 		ctx context.Context
 	}
 	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		wantErr assert.ErrorAssertionFunc
+		name      string
+		fields    fields
+		args      args
+		mockSetup func(t *testing.T, fields *fields, args *args)
+		wantErr   assert.ErrorAssertionFunc
 	}{
 		{
 			name: "connect it",
-			fields: fields{
-				transportInstance: testTransportInstance{},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				instance := NewMockTransportInstance(t)
+				instance.EXPECT().IsConnected().Return(true)
+				fields.transportInstance = instance
 			},
 			wantErr: assert.NoError,
 		},
 		{
 			name: "connect it (fails)",
-			fields: fields{
-				transportInstance: testTransportInstance{
-					connectWithContext: func(_ context.Context) error {
-						return errors.New("nope")
-					},
-				},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				instance := NewMockTransportInstance(t)
+				expect := instance.EXPECT()
+				expect.IsConnected().Return(false)
+				expect.ConnectWithContext(mock.Anything).Return(errors.New("nope"))
+				fields.transportInstance = instance
 			},
 			wantErr: assert.Error,
 		},
 		{
 			name: "connect it already connected",
-			fields: fields{
-				transportInstance: testTransportInstance{
-					connected: true,
-				},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				instance := NewMockTransportInstance(t)
+				instance.EXPECT().IsConnected().Return(true)
+				fields.transportInstance = instance
 			},
 			wantErr: assert.NoError,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields, &tt.args)
+			}
 			m := &defaultCodec{
 				DefaultCodecRequirements:      tt.fields.DefaultCodecRequirements,
 				transportInstance:             tt.fields.transportInstance,
@@ -433,7 +444,11 @@ func Test_defaultCodec_Disconnect(t *testing.T) {
 		{
 			name: "disconnect it",
 			fields: fields{
-				transportInstance: testTransportInstance{},
+				transportInstance: func() transports.TransportInstance {
+					instance := NewMockTransportInstance(t)
+					instance.EXPECT().Close().Return(nil)
+					return instance
+				}(),
 			},
 			wantErr: assert.NoError,
 		},
@@ -711,26 +726,26 @@ func Test_defaultCodec_SendRequest(t *testing.T) {
 		ttl            time.Duration
 	}
 	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		wantErr assert.ErrorAssertionFunc
+		name      string
+		fields    fields
+		args      args
+		mockSetup func(t *testing.T, fields *fields, args *args)
+		wantErr   assert.ErrorAssertionFunc
 	}{
 		{
 			name: "send it",
-			fields: fields{
-				DefaultCodecRequirements: testMessageCodec{},
-			},
 			args: args{
 				ctx: context.Background(),
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultCodecRequirements(t)
+				requirements.EXPECT().Send(mock.Anything).Return(nil)
+				fields.DefaultCodecRequirements = requirements
+			},
 			wantErr: assert.NoError,
 		},
 		{
 			name: "send it canceled",
-			fields: fields{
-				DefaultCodecRequirements: testMessageCodec{},
-			},
 			args: args{
 				ctx: func() context.Context {
 					ctx, cancelFunc := context.WithCancel(context.Background())
@@ -738,25 +753,29 @@ func Test_defaultCodec_SendRequest(t *testing.T) {
 					return ctx
 				}(),
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				fields.DefaultCodecRequirements = NewMockDefaultCodecRequirements(t)
+			},
 			wantErr: assert.Error,
 		},
 		{
 			name: "send it errors",
-			fields: fields{
-				DefaultCodecRequirements: testMessageCodec{
-					send: func(_ spi.Message) error {
-						return errors.New("nope")
-					},
-				},
-			},
 			args: args{
 				ctx: context.Background(),
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultCodecRequirements(t)
+				requirements.EXPECT().Send(mock.Anything).Return(errors.New("nope"))
+				fields.DefaultCodecRequirements = requirements
+			},
 			wantErr: assert.Error,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields, &tt.args)
+			}
 			m := &defaultCodec{
 				DefaultCodecRequirements:      tt.fields.DefaultCodecRequirements,
 				transportInstance:             tt.fields.transportInstance,
@@ -857,9 +876,10 @@ func Test_defaultCodec_Work(t *testing.T) {
 		codec DefaultCodecRequirements
 	}
 	tests := []struct {
-		name   string
-		fields fields
-		args   args
+		name      string
+		fields    fields
+		args      args
+		mockSetup func(t *testing.T, fields *fields, args *args)
 	}{
 		{
 			name: "work it (nothing to do)",
@@ -908,8 +928,7 @@ func Test_defaultCodec_Work(t *testing.T) {
 		{
 			name: "work harder (nil message)",
 			fields: fields{
-				DefaultCodecRequirements: testMessageCodec{},
-				running:                  true,
+				running: true,
 				expectations: []spi.Expectation{
 					&DefaultExpectation{ // Expired
 						Context: context.Background(),
@@ -943,15 +962,15 @@ func Test_defaultCodec_Work(t *testing.T) {
 					},
 				},
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultCodecRequirements(t)
+				requirements.EXPECT().Receive().Return(nil, nil)
+				fields.DefaultCodecRequirements = requirements
+			},
 		},
 		{
 			name: "work harder (message)",
 			fields: fields{
-				DefaultCodecRequirements: testMessageCodec{
-					receive: func() (spi.Message, error) {
-						return testMessage{}, nil
-					},
-				},
 				running: true,
 				expectations: []spi.Expectation{
 					&DefaultExpectation{ // Expired
@@ -986,15 +1005,15 @@ func Test_defaultCodec_Work(t *testing.T) {
 					},
 				},
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultCodecRequirements(t)
+				requirements.EXPECT().Receive().Return(NewMockMessage(t), nil)
+				fields.DefaultCodecRequirements = requirements
+			},
 		},
 		{
 			name: "work harder (message with default channel)",
 			fields: fields{
-				DefaultCodecRequirements: testMessageCodec{
-					receive: func() (spi.Message, error) {
-						return testMessage{}, nil
-					},
-				},
 				defaultIncomingMessageChannel: make(chan spi.Message, 1),
 				running:                       true,
 				expectations: []spi.Expectation{
@@ -1007,15 +1026,15 @@ func Test_defaultCodec_Work(t *testing.T) {
 					},
 				},
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultCodecRequirements(t)
+				requirements.EXPECT().Receive().Return(NewMockMessage(t), nil)
+				fields.DefaultCodecRequirements = requirements
+			},
 		},
 		{
 			name: "work harder (message receive error)",
 			fields: fields{
-				DefaultCodecRequirements: testMessageCodec{
-					receive: func() (spi.Message, error) {
-						return nil, errors.New("nope")
-					},
-				},
 				running: true,
 				expectations: []spi.Expectation{
 					&DefaultExpectation{ // Expired
@@ -1050,15 +1069,15 @@ func Test_defaultCodec_Work(t *testing.T) {
 					},
 				},
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultCodecRequirements(t)
+				requirements.EXPECT().Receive().Return(nil, errors.New("nope"))
+				fields.DefaultCodecRequirements = requirements
+			},
 		},
 		{
 			name: "work harder (message custom not handled)",
 			fields: fields{
-				DefaultCodecRequirements: testMessageCodec{
-					receive: func() (spi.Message, error) {
-						return testMessage{}, nil
-					},
-				},
 				customMessageHandling: func(_ DefaultCodecRequirements, _ spi.Message) bool {
 					return false
 				},
@@ -1096,15 +1115,15 @@ func Test_defaultCodec_Work(t *testing.T) {
 					},
 				},
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultCodecRequirements(t)
+				requirements.EXPECT().Receive().Return(NewMockMessage(t), nil)
+				fields.DefaultCodecRequirements = requirements
+			},
 		},
 		{
 			name: "work harder (message custom handled)",
 			fields: fields{
-				DefaultCodecRequirements: testMessageCodec{
-					receive: func() (spi.Message, error) {
-						return testMessage{}, nil
-					},
-				},
 				customMessageHandling: func(_ DefaultCodecRequirements, _ spi.Message) bool {
 					return true
 				},
@@ -1142,10 +1161,18 @@ func Test_defaultCodec_Work(t *testing.T) {
 					},
 				},
 			},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultCodecRequirements(t)
+				requirements.EXPECT().Receive().Return(NewMockMessage(t), nil)
+				fields.DefaultCodecRequirements = requirements
+			},
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields, &tt.args)
+			}
 			m := &defaultCodec{
 				DefaultCodecRequirements:      tt.fields.DefaultCodecRequirements,
 				transportInstance:             tt.fields.transportInstance,
diff --git a/plc4go/spi/default/DefaultConnection_test.go b/plc4go/spi/default/DefaultConnection_test.go
index f6d46ab64b..76c0e457d1 100644
--- a/plc4go/spi/default/DefaultConnection_test.go
+++ b/plc4go/spi/default/DefaultConnection_test.go
@@ -23,6 +23,7 @@ import (
 	"context"
 	"fmt"
 	"github.com/apache/plc4x/plc4go/spi/utils"
+	"github.com/stretchr/testify/mock"
 	"testing"
 	"time"
 
@@ -429,18 +430,26 @@ func Test_defaultConnection_BlockingClose(t *testing.T) {
 		valueHandler                  spi.PlcValueHandler
 	}
 	tests := []struct {
-		name   string
-		fields fields
+		name      string
+		fields    fields
+		mockSetup func(t *testing.T, fields *fields)
 	}{
 		{
 			name: "close",
-			fields: fields{
-				DefaultConnectionRequirements: testConnection{},
+			mockSetup: func(t *testing.T, fields *fields) {
+				requirements := NewMockDefaultConnectionRequirements(t)
+				connection := NewMockPlcConnection(t)
+				connection.EXPECT().Close().Return(nil)
+				requirements.EXPECT().GetConnection().Return(connection)
+				fields.DefaultConnectionRequirements = requirements
 			},
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields)
+			}
 			d := &defaultConnection{
 				DefaultConnectionRequirements: tt.fields.DefaultConnectionRequirements,
 				defaultTtl:                    tt.fields.defaultTtl,
@@ -469,7 +478,7 @@ func Test_defaultConnection_BrowseRequestBuilder(t *testing.T) {
 		{
 			name: "create it",
 			fields: fields{
-				DefaultConnectionRequirements: testConnection{},
+				DefaultConnectionRequirements: NewMockDefaultConnectionRequirements(t),
 			},
 		},
 	}
@@ -505,12 +514,27 @@ func Test_defaultConnection_Close(t *testing.T) {
 	tests := []struct {
 		name         string
 		fields       fields
+		mockSetup    func(t *testing.T, fields *fields)
 		wantAsserter func(t *testing.T, results <-chan plc4go.PlcConnectionCloseResult) bool
 	}{
 		{
 			name: "close it",
-			fields: fields{
-				DefaultConnectionRequirements: testConnection{},
+			mockSetup: func(t *testing.T, fields *fields) {
+				requirements := NewMockDefaultConnectionRequirements(t)
+				codec := NewMockMessageCodec(t)
+				{
+					expect := codec.EXPECT()
+					expect.Disconnect().Return(nil)
+					instance := NewMockTransportInstance(t)
+					instance.EXPECT().Close().Return(nil)
+					expect.GetTransportInstance().Return(instance)
+				}
+				{
+					expect := requirements.EXPECT()
+					expect.GetMessageCodec().Return(codec)
+					expect.GetConnection().Return(nil)
+				}
+				fields.DefaultConnectionRequirements = requirements
 			},
 			wantAsserter: func(t *testing.T, results <-chan plc4go.PlcConnectionCloseResult) bool {
 				timeout := time.NewTimer(2 * time.Second)
@@ -527,6 +551,9 @@ func Test_defaultConnection_Close(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields)
+			}
 			d := &defaultConnection{
 				DefaultConnectionRequirements: tt.fields.DefaultConnectionRequirements,
 				defaultTtl:                    tt.fields.defaultTtl,
@@ -550,12 +577,18 @@ func Test_defaultConnection_Connect(t *testing.T) {
 	tests := []struct {
 		name         string
 		fields       fields
+		mockSetup    func(t *testing.T, fields *fields)
 		wantAsserter func(t *testing.T, results <-chan plc4go.PlcConnectionConnectResult) bool
 	}{
 		{
 			name: "connect it",
-			fields: fields{
-				DefaultConnectionRequirements: testConnection{},
+			mockSetup: func(t *testing.T, fields *fields) {
+				requirements := NewMockDefaultConnectionRequirements(t)
+				results := make(chan plc4go.PlcConnectionConnectResult, 1)
+				results <- NewMockPlcConnectionConnectResult(t)
+				expect := requirements.EXPECT()
+				expect.ConnectWithContext(mock.Anything).Return(results)
+				fields.DefaultConnectionRequirements = requirements
 			},
 			wantAsserter: func(t *testing.T, results <-chan plc4go.PlcConnectionConnectResult) bool {
 				// Delegated call is tested below
@@ -565,6 +598,9 @@ func Test_defaultConnection_Connect(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields)
+			}
 			d := &defaultConnection{
 				DefaultConnectionRequirements: tt.fields.DefaultConnectionRequirements,
 				defaultTtl:                    tt.fields.defaultTtl,
@@ -592,12 +628,21 @@ func Test_defaultConnection_ConnectWithContext(t *testing.T) {
 		name         string
 		fields       fields
 		args         args
+		mockSetup    func(t *testing.T, fields *fields, args *args)
 		wantAsserter func(t *testing.T, results <-chan plc4go.PlcConnectionConnectResult) bool
 	}{
 		{
 			name: "connect it",
-			fields: fields{
-				DefaultConnectionRequirements: testConnection{},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultConnectionRequirements(t)
+				codec := NewMockMessageCodec(t)
+				{
+					codec.EXPECT().ConnectWithContext(mock.Anything).Return(nil)
+				}
+				expect := requirements.EXPECT()
+				expect.GetMessageCodec().Return(codec)
+				expect.GetConnection().Return(NewMockPlcConnection(t))
+				fields.DefaultConnectionRequirements = requirements
 			},
 			wantAsserter: func(t *testing.T, results <-chan plc4go.PlcConnectionConnectResult) bool {
 				timeout := time.NewTimer(2 * time.Second)
@@ -614,6 +659,9 @@ func Test_defaultConnection_ConnectWithContext(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields, &tt.args)
+			}
 			d := &defaultConnection{
 				DefaultConnectionRequirements: tt.fields.DefaultConnectionRequirements,
 				defaultTtl:                    tt.fields.defaultTtl,
@@ -728,21 +776,32 @@ func Test_defaultConnection_GetTransportInstance(t *testing.T) {
 		tagHandler                    spi.PlcTagHandler
 		valueHandler                  spi.PlcValueHandler
 	}
+	theInstance := NewMockTransportInstance(t)
 	tests := []struct {
-		name   string
-		fields fields
-		want   transports.TransportInstance
+		name      string
+		fields    fields
+		mockSetup func(t *testing.T, fields *fields)
+		want      transports.TransportInstance
 	}{
 		{
 			name: "get it",
-			fields: fields{
-				DefaultConnectionRequirements: testConnection{},
+			mockSetup: func(t *testing.T, fields *fields) {
+				requirements := NewMockDefaultConnectionRequirements(t)
+				codec := NewMockMessageCodec(t)
+				{
+					codec.EXPECT().GetTransportInstance().Return(theInstance)
+				}
+				requirements.EXPECT().GetMessageCodec().Return(codec)
+				fields.DefaultConnectionRequirements = requirements
 			},
-			want: testTransportInstance{},
+			want: theInstance,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields)
+			}
 			d := &defaultConnection{
 				DefaultConnectionRequirements: tt.fields.DefaultConnectionRequirements,
 				defaultTtl:                    tt.fields.defaultTtl,
@@ -828,12 +887,19 @@ func Test_defaultConnection_Ping(t *testing.T) {
 	tests := []struct {
 		name         string
 		fields       fields
+		mockSetup    func(t *testing.T, fields *fields)
 		wantAsserter func(t *testing.T, results <-chan plc4go.PlcConnectionPingResult) bool
 	}{
 		{
 			name: "ping it",
-			fields: fields{
-				DefaultConnectionRequirements: testConnection{},
+			mockSetup: func(t *testing.T, fields *fields) {
+				requirements := NewMockDefaultConnectionRequirements(t)
+				connection := NewMockPlcConnection(t)
+				{
+					connection.EXPECT().IsConnected().Return(false)
+				}
+				requirements.EXPECT().GetConnection().Return(connection)
+				fields.DefaultConnectionRequirements = requirements
 			},
 			wantAsserter: func(t *testing.T, results <-chan plc4go.PlcConnectionPingResult) bool {
 				timeout := time.NewTimer(2 * time.Second)
@@ -850,11 +916,17 @@ func Test_defaultConnection_Ping(t *testing.T) {
 		{
 			name: "ping it connected",
 			fields: fields{
-				DefaultConnectionRequirements: testConnection{
-					connected: true,
-				},
 				connected: true,
 			},
+			mockSetup: func(t *testing.T, fields *fields) {
+				requirements := NewMockDefaultConnectionRequirements(t)
+				connection := NewMockPlcConnection(t)
+				{
+					connection.EXPECT().IsConnected().Return(true)
+				}
+				requirements.EXPECT().GetConnection().Return(connection)
+				fields.DefaultConnectionRequirements = requirements
+			},
 			wantAsserter: func(t *testing.T, results <-chan plc4go.PlcConnectionPingResult) bool {
 				timeout := time.NewTimer(2 * time.Second)
 				defer utils.CleanupTimer(timeout)
@@ -870,6 +942,9 @@ func Test_defaultConnection_Ping(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields)
+			}
 			d := &defaultConnection{
 				DefaultConnectionRequirements: tt.fields.DefaultConnectionRequirements,
 				defaultTtl:                    tt.fields.defaultTtl,
@@ -1109,7 +1184,7 @@ func Test_plcConnectionCloseResult_GetErr(t *testing.T) {
 		{
 			name: "get it",
 			fields: fields{
-				connection: testConnection{},
+				connection: NewMockPlcConnection(t),
 			},
 			wantErr: assert.NoError,
 		},
@@ -1191,7 +1266,7 @@ func Test_plcConnectionConnectResult_GetErr(t *testing.T) {
 		{
 			name: "get it",
 			fields: fields{
-				connection: testConnection{},
+				connection: NewMockPlcConnection(t),
 			},
 			wantErr: assert.NoError,
 		},
diff --git a/plc4go/spi/default/DefaultDriver_test.go b/plc4go/spi/default/DefaultDriver_test.go
index 906e20f85c..9aa1e95ec2 100644
--- a/plc4go/spi/default/DefaultDriver_test.go
+++ b/plc4go/spi/default/DefaultDriver_test.go
@@ -23,6 +23,7 @@ import (
 	"context"
 	"fmt"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
 	"net/url"
 	"testing"
 
@@ -70,21 +71,27 @@ func Test_defaultDriver_CheckQuery(t *testing.T) {
 		query string
 	}
 	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		wantErr assert.ErrorAssertionFunc
+		name      string
+		fields    fields
+		args      args
+		mockSetup func(t *testing.T, fields *fields, args *args)
+		wantErr   assert.ErrorAssertionFunc
 	}{
 		{
 			name: "check it",
-			fields: fields{
-				plcTagHandler: testTagHandler{},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				handler := NewMockPlcTagHandler(t)
+				handler.EXPECT().ParseQuery(mock.Anything).Return(nil, nil)
+				fields.plcTagHandler = handler
 			},
 			wantErr: assert.NoError,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields, &tt.args)
+			}
 			d := &defaultDriver{
 				DefaultDriverRequirements: tt.fields.DefaultDriverRequirements,
 				protocolCode:              tt.fields.protocolCode,
@@ -109,21 +116,27 @@ func Test_defaultDriver_CheckTagAddress(t *testing.T) {
 		query string
 	}
 	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		wantErr assert.ErrorAssertionFunc
+		name      string
+		fields    fields
+		args      args
+		mockSetup func(t *testing.T, fields *fields, args *args)
+		wantErr   assert.ErrorAssertionFunc
 	}{
 		{
 			name: "check it",
-			fields: fields{
-				plcTagHandler: testTagHandler{},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				handler := NewMockPlcTagHandler(t)
+				handler.EXPECT().ParseTag(mock.Anything).Return(nil, nil)
+				fields.plcTagHandler = handler
 			},
 			wantErr: assert.NoError,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields, &tt.args)
+			}
 			d := &defaultDriver{
 				DefaultDriverRequirements: tt.fields.DefaultDriverRequirements,
 				protocolCode:              tt.fields.protocolCode,
@@ -149,21 +162,27 @@ func Test_defaultDriver_Discover(t *testing.T) {
 		discoveryOptions []options.WithDiscoveryOption
 	}
 	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		wantErr assert.ErrorAssertionFunc
+		name      string
+		fields    fields
+		args      args
+		mockSetup func(t *testing.T, fields *fields, args *args)
+		wantErr   assert.ErrorAssertionFunc
 	}{
 		{
 			name: "discover it",
-			fields: fields{
-				DefaultDriverRequirements: testDriver{},
+			mockSetup: func(t *testing.T, fields *fields, args *args) {
+				requirements := NewMockDefaultDriverRequirements(t)
+				requirements.EXPECT().DiscoverWithContext(mock.Anything, mock.Anything).Return(nil)
+				fields.DefaultDriverRequirements = requirements
 			},
 			wantErr: assert.NoError,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields, &tt.args)
+			}
 			d := &defaultDriver{
 				DefaultDriverRequirements: tt.fields.DefaultDriverRequirements,
 				protocolCode:              tt.fields.protocolCode,
@@ -228,21 +247,29 @@ func Test_defaultDriver_GetConnection(t *testing.T) {
 		options      map[string][]string
 	}
 	tests := []struct {
-		name   string
-		fields fields
-		args   args
-		want   <-chan plc4go.PlcConnectionConnectResult
+		name      string
+		fields    fields
+		args      args
+		mockSetup func(t *testing.T, fields *fields, args *args, want *<-chan plc4go.PlcConnectionConnectResult)
+		want      <-chan plc4go.PlcConnectionConnectResult
 	}{
 		{
 			name: "get a connection",
-			fields: fields{
-				DefaultDriverRequirements: testDriver{},
+			mockSetup: func(t *testing.T, fields *fields, args *args, want *<-chan plc4go.PlcConnectionConnectResult) {
+				requirements := NewMockDefaultDriverRequirements(t)
+				results := make(chan plc4go.PlcConnectionConnectResult, 1)
+				*want = results
+				results <- NewMockPlcConnectionConnectResult(t)
+				requirements.EXPECT().GetConnectionWithContext(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(results)
+				fields.DefaultDriverRequirements = requirements
 			},
-			args: args{},
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields, &tt.args, &tt.want)
+			}
 			d := &defaultDriver{
 				DefaultDriverRequirements: tt.fields.DefaultDriverRequirements,
 				protocolCode:              tt.fields.protocolCode,
diff --git a/plc4go/spi/default/mock_MessageCodec_test.go b/plc4go/spi/default/mock_MessageCodec_test.go
new file mode 100644
index 0000000000..f90e7062fe
--- /dev/null
+++ b/plc4go/spi/default/mock_MessageCodec_test.go
@@ -0,0 +1,447 @@
+/*
+ * 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
+ *
+ *   https://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.
+ */
+
+// Code generated by mockery v2.26.1. DO NOT EDIT.
+
+package _default
+
+import (
+	context "context"
+
+	spi "github.com/apache/plc4x/plc4go/spi"
+	mock "github.com/stretchr/testify/mock"
+
+	time "time"
+
+	transports "github.com/apache/plc4x/plc4go/spi/transports"
+)
+
+// MockMessageCodec is an autogenerated mock type for the MessageCodec type
+type MockMessageCodec struct {
+	mock.Mock
+}
+
+type MockMessageCodec_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockMessageCodec) EXPECT() *MockMessageCodec_Expecter {
+	return &MockMessageCodec_Expecter{mock: &_m.Mock}
+}
+
+// Connect provides a mock function with given fields:
+func (_m *MockMessageCodec) Connect() error {
+	ret := _m.Called()
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func() error); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockMessageCodec_Connect_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Connect'
+type MockMessageCodec_Connect_Call struct {
+	*mock.Call
+}
+
+// Connect is a helper method to define mock.On call
+func (_e *MockMessageCodec_Expecter) Connect() *MockMessageCodec_Connect_Call {
+	return &MockMessageCodec_Connect_Call{Call: _e.mock.On("Connect")}
+}
+
+func (_c *MockMessageCodec_Connect_Call) Run(run func()) *MockMessageCodec_Connect_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockMessageCodec_Connect_Call) Return(_a0 error) *MockMessageCodec_Connect_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessageCodec_Connect_Call) RunAndReturn(run func() error) *MockMessageCodec_Connect_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// ConnectWithContext provides a mock function with given fields: ctx
+func (_m *MockMessageCodec) ConnectWithContext(ctx context.Context) error {
+	ret := _m.Called(ctx)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(context.Context) error); ok {
+		r0 = rf(ctx)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockMessageCodec_ConnectWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConnectWithContext'
+type MockMessageCodec_ConnectWithContext_Call struct {
+	*mock.Call
+}
+
+// ConnectWithContext is a helper method to define mock.On call
+//   - ctx context.Context
+func (_e *MockMessageCodec_Expecter) ConnectWithContext(ctx interface{}) *MockMessageCodec_ConnectWithContext_Call {
+	return &MockMessageCodec_ConnectWithContext_Call{Call: _e.mock.On("ConnectWithContext", ctx)}
+}
+
+func (_c *MockMessageCodec_ConnectWithContext_Call) Run(run func(ctx context.Context)) *MockMessageCodec_ConnectWithContext_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context))
+	})
+	return _c
+}
+
+func (_c *MockMessageCodec_ConnectWithContext_Call) Return(_a0 error) *MockMessageCodec_ConnectWithContext_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessageCodec_ConnectWithContext_Call) RunAndReturn(run func(context.Context) error) *MockMessageCodec_ConnectWithContext_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Disconnect provides a mock function with given fields:
+func (_m *MockMessageCodec) Disconnect() error {
+	ret := _m.Called()
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func() error); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockMessageCodec_Disconnect_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Disconnect'
+type MockMessageCodec_Disconnect_Call struct {
+	*mock.Call
+}
+
+// Disconnect is a helper method to define mock.On call
+func (_e *MockMessageCodec_Expecter) Disconnect() *MockMessageCodec_Disconnect_Call {
+	return &MockMessageCodec_Disconnect_Call{Call: _e.mock.On("Disconnect")}
+}
+
+func (_c *MockMessageCodec_Disconnect_Call) Run(run func()) *MockMessageCodec_Disconnect_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockMessageCodec_Disconnect_Call) Return(_a0 error) *MockMessageCodec_Disconnect_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessageCodec_Disconnect_Call) RunAndReturn(run func() error) *MockMessageCodec_Disconnect_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Expect provides a mock function with given fields: ctx, acceptsMessage, handleMessage, handleError, ttl
+func (_m *MockMessageCodec) Expect(ctx context.Context, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError, ttl time.Duration) error {
+	ret := _m.Called(ctx, acceptsMessage, handleMessage, handleError, ttl)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(context.Context, spi.AcceptsMessage, spi.HandleMessage, spi.HandleError, time.Duration) error); ok {
+		r0 = rf(ctx, acceptsMessage, handleMessage, handleError, ttl)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockMessageCodec_Expect_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Expect'
+type MockMessageCodec_Expect_Call struct {
+	*mock.Call
+}
+
+// Expect is a helper method to define mock.On call
+//   - ctx context.Context
+//   - acceptsMessage spi.AcceptsMessage
+//   - handleMessage spi.HandleMessage
+//   - handleError spi.HandleError
+//   - ttl time.Duration
+func (_e *MockMessageCodec_Expecter) Expect(ctx interface{}, acceptsMessage interface{}, handleMessage interface{}, handleError interface{}, ttl interface{}) *MockMessageCodec_Expect_Call {
+	return &MockMessageCodec_Expect_Call{Call: _e.mock.On("Expect", ctx, acceptsMessage, handleMessage, handleError, ttl)}
+}
+
+func (_c *MockMessageCodec_Expect_Call) Run(run func(ctx context.Context, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError, ttl time.Duration)) *MockMessageCodec_Expect_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(spi.AcceptsMessage), args[2].(spi.HandleMessage), args[3].(spi.HandleError), args[4].(time.Duration))
+	})
+	return _c
+}
+
+func (_c *MockMessageCodec_Expect_Call) Return(_a0 error) *MockMessageCodec_Expect_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessageCodec_Expect_Call) RunAndReturn(run func(context.Context, spi.AcceptsMessage, spi.HandleMessage, spi.HandleError, time.Duration) error) *MockMessageCodec_Expect_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// GetDefaultIncomingMessageChannel provides a mock function with given fields:
+func (_m *MockMessageCodec) GetDefaultIncomingMessageChannel() chan spi.Message {
+	ret := _m.Called()
+
+	var r0 chan spi.Message
+	if rf, ok := ret.Get(0).(func() chan spi.Message); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(chan spi.Message)
+		}
+	}
+
+	return r0
+}
+
+// MockMessageCodec_GetDefaultIncomingMessageChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDefaultIncomingMessageChannel'
+type MockMessageCodec_GetDefaultIncomingMessageChannel_Call struct {
+	*mock.Call
+}
+
+// GetDefaultIncomingMessageChannel is a helper method to define mock.On call
+func (_e *MockMessageCodec_Expecter) GetDefaultIncomingMessageChannel() *MockMessageCodec_GetDefaultIncomingMessageChannel_Call {
+	return &MockMessageCodec_GetDefaultIncomingMessageChannel_Call{Call: _e.mock.On("GetDefaultIncomingMessageChannel")}
+}
+
+func (_c *MockMessageCodec_GetDefaultIncomingMessageChannel_Call) Run(run func()) *MockMessageCodec_GetDefaultIncomingMessageChannel_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockMessageCodec_GetDefaultIncomingMessageChannel_Call) Return(_a0 chan spi.Message) *MockMessageCodec_GetDefaultIncomingMessageChannel_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessageCodec_GetDefaultIncomingMessageChannel_Call) RunAndReturn(run func() chan spi.Message) *MockMessageCodec_GetDefaultIncomingMessageChannel_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// GetTransportInstance provides a mock function with given fields:
+func (_m *MockMessageCodec) GetTransportInstance() transports.TransportInstance {
+	ret := _m.Called()
+
+	var r0 transports.TransportInstance
+	if rf, ok := ret.Get(0).(func() transports.TransportInstance); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(transports.TransportInstance)
+		}
+	}
+
+	return r0
+}
+
+// MockMessageCodec_GetTransportInstance_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransportInstance'
+type MockMessageCodec_GetTransportInstance_Call struct {
+	*mock.Call
+}
+
+// GetTransportInstance is a helper method to define mock.On call
+func (_e *MockMessageCodec_Expecter) GetTransportInstance() *MockMessageCodec_GetTransportInstance_Call {
+	return &MockMessageCodec_GetTransportInstance_Call{Call: _e.mock.On("GetTransportInstance")}
+}
+
+func (_c *MockMessageCodec_GetTransportInstance_Call) Run(run func()) *MockMessageCodec_GetTransportInstance_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockMessageCodec_GetTransportInstance_Call) Return(_a0 transports.TransportInstance) *MockMessageCodec_GetTransportInstance_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessageCodec_GetTransportInstance_Call) RunAndReturn(run func() transports.TransportInstance) *MockMessageCodec_GetTransportInstance_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// IsRunning provides a mock function with given fields:
+func (_m *MockMessageCodec) IsRunning() bool {
+	ret := _m.Called()
+
+	var r0 bool
+	if rf, ok := ret.Get(0).(func() bool); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(bool)
+	}
+
+	return r0
+}
+
+// MockMessageCodec_IsRunning_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsRunning'
+type MockMessageCodec_IsRunning_Call struct {
+	*mock.Call
+}
+
+// IsRunning is a helper method to define mock.On call
+func (_e *MockMessageCodec_Expecter) IsRunning() *MockMessageCodec_IsRunning_Call {
+	return &MockMessageCodec_IsRunning_Call{Call: _e.mock.On("IsRunning")}
+}
+
+func (_c *MockMessageCodec_IsRunning_Call) Run(run func()) *MockMessageCodec_IsRunning_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockMessageCodec_IsRunning_Call) Return(_a0 bool) *MockMessageCodec_IsRunning_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessageCodec_IsRunning_Call) RunAndReturn(run func() bool) *MockMessageCodec_IsRunning_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Send provides a mock function with given fields: message
+func (_m *MockMessageCodec) Send(message spi.Message) error {
+	ret := _m.Called(message)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(spi.Message) error); ok {
+		r0 = rf(message)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockMessageCodec_Send_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Send'
+type MockMessageCodec_Send_Call struct {
+	*mock.Call
+}
+
+// Send is a helper method to define mock.On call
+//   - message spi.Message
+func (_e *MockMessageCodec_Expecter) Send(message interface{}) *MockMessageCodec_Send_Call {
+	return &MockMessageCodec_Send_Call{Call: _e.mock.On("Send", message)}
+}
+
+func (_c *MockMessageCodec_Send_Call) Run(run func(message spi.Message)) *MockMessageCodec_Send_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(spi.Message))
+	})
+	return _c
+}
+
+func (_c *MockMessageCodec_Send_Call) Return(_a0 error) *MockMessageCodec_Send_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessageCodec_Send_Call) RunAndReturn(run func(spi.Message) error) *MockMessageCodec_Send_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// SendRequest provides a mock function with given fields: ctx, message, acceptsMessage, handleMessage, handleError, ttl
+func (_m *MockMessageCodec) SendRequest(ctx context.Context, message spi.Message, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError, ttl time.Duration) error {
+	ret := _m.Called(ctx, message, acceptsMessage, handleMessage, handleError, ttl)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(context.Context, spi.Message, spi.AcceptsMessage, spi.HandleMessage, spi.HandleError, time.Duration) error); ok {
+		r0 = rf(ctx, message, acceptsMessage, handleMessage, handleError, ttl)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockMessageCodec_SendRequest_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendRequest'
+type MockMessageCodec_SendRequest_Call struct {
+	*mock.Call
+}
+
+// SendRequest is a helper method to define mock.On call
+//   - ctx context.Context
+//   - message spi.Message
+//   - acceptsMessage spi.AcceptsMessage
+//   - handleMessage spi.HandleMessage
+//   - handleError spi.HandleError
+//   - ttl time.Duration
+func (_e *MockMessageCodec_Expecter) SendRequest(ctx interface{}, message interface{}, acceptsMessage interface{}, handleMessage interface{}, handleError interface{}, ttl interface{}) *MockMessageCodec_SendRequest_Call {
+	return &MockMessageCodec_SendRequest_Call{Call: _e.mock.On("SendRequest", ctx, message, acceptsMessage, handleMessage, handleError, ttl)}
+}
+
+func (_c *MockMessageCodec_SendRequest_Call) Run(run func(ctx context.Context, message spi.Message, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError, ttl time.Duration)) *MockMessageCodec_SendRequest_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(spi.Message), args[2].(spi.AcceptsMessage), args[3].(spi.HandleMessage), args[4].(spi.HandleError), args[5].(time.Duration))
+	})
+	return _c
+}
+
+func (_c *MockMessageCodec_SendRequest_Call) Return(_a0 error) *MockMessageCodec_SendRequest_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessageCodec_SendRequest_Call) RunAndReturn(run func(context.Context, spi.Message, spi.AcceptsMessage, spi.HandleMessage, spi.HandleError, time.Duration) error) *MockMessageCodec_SendRequest_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockMessageCodec interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockMessageCodec creates a new instance of MockMessageCodec. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockMessageCodec(t mockConstructorTestingTNewMockMessageCodec) *MockMessageCodec {
+	mock := &MockMessageCodec{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/default/mock_Message_test.go b/plc4go/spi/default/mock_Message_test.go
new file mode 100644
index 0000000000..2a32a6a412
--- /dev/null
+++ b/plc4go/spi/default/mock_Message_test.go
@@ -0,0 +1,237 @@
+/*
+ * 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
+ *
+ *   https://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.
+ */
+
+// Code generated by mockery v2.26.1. DO NOT EDIT.
+
+package _default
+
+import (
+	context "context"
+
+	utils "github.com/apache/plc4x/plc4go/spi/utils"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// MockMessage is an autogenerated mock type for the Message type
+type MockMessage struct {
+	mock.Mock
+}
+
+type MockMessage_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockMessage) EXPECT() *MockMessage_Expecter {
+	return &MockMessage_Expecter{mock: &_m.Mock}
+}
+
+// GetLengthInBits provides a mock function with given fields: ctx
+func (_m *MockMessage) GetLengthInBits(ctx context.Context) uint16 {
+	ret := _m.Called(ctx)
+
+	var r0 uint16
+	if rf, ok := ret.Get(0).(func(context.Context) uint16); ok {
+		r0 = rf(ctx)
+	} else {
+		r0 = ret.Get(0).(uint16)
+	}
+
+	return r0
+}
+
+// MockMessage_GetLengthInBits_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLengthInBits'
+type MockMessage_GetLengthInBits_Call struct {
+	*mock.Call
+}
+
+// GetLengthInBits is a helper method to define mock.On call
+//   - ctx context.Context
+func (_e *MockMessage_Expecter) GetLengthInBits(ctx interface{}) *MockMessage_GetLengthInBits_Call {
+	return &MockMessage_GetLengthInBits_Call{Call: _e.mock.On("GetLengthInBits", ctx)}
+}
+
+func (_c *MockMessage_GetLengthInBits_Call) Run(run func(ctx context.Context)) *MockMessage_GetLengthInBits_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context))
+	})
+	return _c
+}
+
+func (_c *MockMessage_GetLengthInBits_Call) Return(_a0 uint16) *MockMessage_GetLengthInBits_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessage_GetLengthInBits_Call) RunAndReturn(run func(context.Context) uint16) *MockMessage_GetLengthInBits_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// GetLengthInBytes provides a mock function with given fields: ctx
+func (_m *MockMessage) GetLengthInBytes(ctx context.Context) uint16 {
+	ret := _m.Called(ctx)
+
+	var r0 uint16
+	if rf, ok := ret.Get(0).(func(context.Context) uint16); ok {
+		r0 = rf(ctx)
+	} else {
+		r0 = ret.Get(0).(uint16)
+	}
+
+	return r0
+}
+
+// MockMessage_GetLengthInBytes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetLengthInBytes'
+type MockMessage_GetLengthInBytes_Call struct {
+	*mock.Call
+}
+
+// GetLengthInBytes is a helper method to define mock.On call
+//   - ctx context.Context
+func (_e *MockMessage_Expecter) GetLengthInBytes(ctx interface{}) *MockMessage_GetLengthInBytes_Call {
+	return &MockMessage_GetLengthInBytes_Call{Call: _e.mock.On("GetLengthInBytes", ctx)}
+}
+
+func (_c *MockMessage_GetLengthInBytes_Call) Run(run func(ctx context.Context)) *MockMessage_GetLengthInBytes_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context))
+	})
+	return _c
+}
+
+func (_c *MockMessage_GetLengthInBytes_Call) Return(_a0 uint16) *MockMessage_GetLengthInBytes_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessage_GetLengthInBytes_Call) RunAndReturn(run func(context.Context) uint16) *MockMessage_GetLengthInBytes_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Serialize provides a mock function with given fields:
+func (_m *MockMessage) Serialize() ([]byte, error) {
+	ret := _m.Called()
+
+	var r0 []byte
+	var r1 error
+	if rf, ok := ret.Get(0).(func() ([]byte, error)); ok {
+		return rf()
+	}
+	if rf, ok := ret.Get(0).(func() []byte); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]byte)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func() error); ok {
+		r1 = rf()
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MockMessage_Serialize_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Serialize'
+type MockMessage_Serialize_Call struct {
+	*mock.Call
+}
+
+// Serialize is a helper method to define mock.On call
+func (_e *MockMessage_Expecter) Serialize() *MockMessage_Serialize_Call {
+	return &MockMessage_Serialize_Call{Call: _e.mock.On("Serialize")}
+}
+
+func (_c *MockMessage_Serialize_Call) Run(run func()) *MockMessage_Serialize_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockMessage_Serialize_Call) Return(_a0 []byte, _a1 error) *MockMessage_Serialize_Call {
+	_c.Call.Return(_a0, _a1)
+	return _c
+}
+
+func (_c *MockMessage_Serialize_Call) RunAndReturn(run func() ([]byte, error)) *MockMessage_Serialize_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// SerializeWithWriteBuffer provides a mock function with given fields: ctx, writeBuffer
+func (_m *MockMessage) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error {
+	ret := _m.Called(ctx, writeBuffer)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(context.Context, utils.WriteBuffer) error); ok {
+		r0 = rf(ctx, writeBuffer)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockMessage_SerializeWithWriteBuffer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SerializeWithWriteBuffer'
+type MockMessage_SerializeWithWriteBuffer_Call struct {
+	*mock.Call
+}
+
+// SerializeWithWriteBuffer is a helper method to define mock.On call
+//   - ctx context.Context
+//   - writeBuffer utils.WriteBuffer
+func (_e *MockMessage_Expecter) SerializeWithWriteBuffer(ctx interface{}, writeBuffer interface{}) *MockMessage_SerializeWithWriteBuffer_Call {
+	return &MockMessage_SerializeWithWriteBuffer_Call{Call: _e.mock.On("SerializeWithWriteBuffer", ctx, writeBuffer)}
+}
+
+func (_c *MockMessage_SerializeWithWriteBuffer_Call) Run(run func(ctx context.Context, writeBuffer utils.WriteBuffer)) *MockMessage_SerializeWithWriteBuffer_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(utils.WriteBuffer))
+	})
+	return _c
+}
+
+func (_c *MockMessage_SerializeWithWriteBuffer_Call) Return(_a0 error) *MockMessage_SerializeWithWriteBuffer_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockMessage_SerializeWithWriteBuffer_Call) RunAndReturn(run func(context.Context, utils.WriteBuffer) error) *MockMessage_SerializeWithWriteBuffer_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockMessage interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockMessage creates a new instance of MockMessage. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockMessage(t mockConstructorTestingTNewMockMessage) *MockMessage {
+	mock := &MockMessage{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/default/mock_PlcConnectionConnectResult_test.go b/plc4go/spi/default/mock_PlcConnectionConnectResult_test.go
new file mode 100644
index 0000000000..2f46bbb847
--- /dev/null
+++ b/plc4go/spi/default/mock_PlcConnectionConnectResult_test.go
@@ -0,0 +1,139 @@
+/*
+ * 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
+ *
+ *   https://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.
+ */
+
+// Code generated by mockery v2.26.1. DO NOT EDIT.
+
+package _default
+
+import (
+	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// MockPlcConnectionConnectResult is an autogenerated mock type for the PlcConnectionConnectResult type
+type MockPlcConnectionConnectResult struct {
+	mock.Mock
+}
+
+type MockPlcConnectionConnectResult_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockPlcConnectionConnectResult) EXPECT() *MockPlcConnectionConnectResult_Expecter {
+	return &MockPlcConnectionConnectResult_Expecter{mock: &_m.Mock}
+}
+
+// GetConnection provides a mock function with given fields:
+func (_m *MockPlcConnectionConnectResult) GetConnection() plc4go.PlcConnection {
+	ret := _m.Called()
+
+	var r0 plc4go.PlcConnection
+	if rf, ok := ret.Get(0).(func() plc4go.PlcConnection); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(plc4go.PlcConnection)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnectionConnectResult_GetConnection_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetConnection'
+type MockPlcConnectionConnectResult_GetConnection_Call struct {
+	*mock.Call
+}
+
+// GetConnection is a helper method to define mock.On call
+func (_e *MockPlcConnectionConnectResult_Expecter) GetConnection() *MockPlcConnectionConnectResult_GetConnection_Call {
+	return &MockPlcConnectionConnectResult_GetConnection_Call{Call: _e.mock.On("GetConnection")}
+}
+
+func (_c *MockPlcConnectionConnectResult_GetConnection_Call) Run(run func()) *MockPlcConnectionConnectResult_GetConnection_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnectionConnectResult_GetConnection_Call) Return(_a0 plc4go.PlcConnection) *MockPlcConnectionConnectResult_GetConnection_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnectionConnectResult_GetConnection_Call) RunAndReturn(run func() plc4go.PlcConnection) *MockPlcConnectionConnectResult_GetConnection_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// GetErr provides a mock function with given fields:
+func (_m *MockPlcConnectionConnectResult) GetErr() error {
+	ret := _m.Called()
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func() error); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockPlcConnectionConnectResult_GetErr_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetErr'
+type MockPlcConnectionConnectResult_GetErr_Call struct {
+	*mock.Call
+}
+
+// GetErr is a helper method to define mock.On call
+func (_e *MockPlcConnectionConnectResult_Expecter) GetErr() *MockPlcConnectionConnectResult_GetErr_Call {
+	return &MockPlcConnectionConnectResult_GetErr_Call{Call: _e.mock.On("GetErr")}
+}
+
+func (_c *MockPlcConnectionConnectResult_GetErr_Call) Run(run func()) *MockPlcConnectionConnectResult_GetErr_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnectionConnectResult_GetErr_Call) Return(_a0 error) *MockPlcConnectionConnectResult_GetErr_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnectionConnectResult_GetErr_Call) RunAndReturn(run func() error) *MockPlcConnectionConnectResult_GetErr_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockPlcConnectionConnectResult interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockPlcConnectionConnectResult creates a new instance of MockPlcConnectionConnectResult. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockPlcConnectionConnectResult(t mockConstructorTestingTNewMockPlcConnectionConnectResult) *MockPlcConnectionConnectResult {
+	mock := &MockPlcConnectionConnectResult{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/default/mock_PlcConnection_test.go b/plc4go/spi/default/mock_PlcConnection_test.go
new file mode 100644
index 0000000000..e4a465fc62
--- /dev/null
+++ b/plc4go/spi/default/mock_PlcConnection_test.go
@@ -0,0 +1,563 @@
+/*
+ * 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
+ *
+ *   https://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.
+ */
+
+// Code generated by mockery v2.26.1. DO NOT EDIT.
+
+package _default
+
+import (
+	context "context"
+
+	model "github.com/apache/plc4x/plc4go/pkg/api/model"
+	mock "github.com/stretchr/testify/mock"
+
+	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
+)
+
+// MockPlcConnection is an autogenerated mock type for the PlcConnection type
+type MockPlcConnection struct {
+	mock.Mock
+}
+
+type MockPlcConnection_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockPlcConnection) EXPECT() *MockPlcConnection_Expecter {
+	return &MockPlcConnection_Expecter{mock: &_m.Mock}
+}
+
+// BlockingClose provides a mock function with given fields:
+func (_m *MockPlcConnection) BlockingClose() {
+	_m.Called()
+}
+
+// MockPlcConnection_BlockingClose_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BlockingClose'
+type MockPlcConnection_BlockingClose_Call struct {
+	*mock.Call
+}
+
+// BlockingClose is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) BlockingClose() *MockPlcConnection_BlockingClose_Call {
+	return &MockPlcConnection_BlockingClose_Call{Call: _e.mock.On("BlockingClose")}
+}
+
+func (_c *MockPlcConnection_BlockingClose_Call) Run(run func()) *MockPlcConnection_BlockingClose_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_BlockingClose_Call) Return() *MockPlcConnection_BlockingClose_Call {
+	_c.Call.Return()
+	return _c
+}
+
+func (_c *MockPlcConnection_BlockingClose_Call) RunAndReturn(run func()) *MockPlcConnection_BlockingClose_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// BrowseRequestBuilder provides a mock function with given fields:
+func (_m *MockPlcConnection) BrowseRequestBuilder() model.PlcBrowseRequestBuilder {
+	ret := _m.Called()
+
+	var r0 model.PlcBrowseRequestBuilder
+	if rf, ok := ret.Get(0).(func() model.PlcBrowseRequestBuilder); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(model.PlcBrowseRequestBuilder)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_BrowseRequestBuilder_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BrowseRequestBuilder'
+type MockPlcConnection_BrowseRequestBuilder_Call struct {
+	*mock.Call
+}
+
+// BrowseRequestBuilder is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) BrowseRequestBuilder() *MockPlcConnection_BrowseRequestBuilder_Call {
+	return &MockPlcConnection_BrowseRequestBuilder_Call{Call: _e.mock.On("BrowseRequestBuilder")}
+}
+
+func (_c *MockPlcConnection_BrowseRequestBuilder_Call) Run(run func()) *MockPlcConnection_BrowseRequestBuilder_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_BrowseRequestBuilder_Call) Return(_a0 model.PlcBrowseRequestBuilder) *MockPlcConnection_BrowseRequestBuilder_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_BrowseRequestBuilder_Call) RunAndReturn(run func() model.PlcBrowseRequestBuilder) *MockPlcConnection_BrowseRequestBuilder_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Close provides a mock function with given fields:
+func (_m *MockPlcConnection) Close() <-chan plc4go.PlcConnectionCloseResult {
+	ret := _m.Called()
+
+	var r0 <-chan plc4go.PlcConnectionCloseResult
+	if rf, ok := ret.Get(0).(func() <-chan plc4go.PlcConnectionCloseResult); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(<-chan plc4go.PlcConnectionCloseResult)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
+type MockPlcConnection_Close_Call struct {
+	*mock.Call
+}
+
+// Close is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) Close() *MockPlcConnection_Close_Call {
+	return &MockPlcConnection_Close_Call{Call: _e.mock.On("Close")}
+}
+
+func (_c *MockPlcConnection_Close_Call) Run(run func()) *MockPlcConnection_Close_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_Close_Call) Return(_a0 <-chan plc4go.PlcConnectionCloseResult) *MockPlcConnection_Close_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_Close_Call) RunAndReturn(run func() <-chan plc4go.PlcConnectionCloseResult) *MockPlcConnection_Close_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Connect provides a mock function with given fields:
+func (_m *MockPlcConnection) Connect() <-chan plc4go.PlcConnectionConnectResult {
+	ret := _m.Called()
+
+	var r0 <-chan plc4go.PlcConnectionConnectResult
+	if rf, ok := ret.Get(0).(func() <-chan plc4go.PlcConnectionConnectResult); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(<-chan plc4go.PlcConnectionConnectResult)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_Connect_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Connect'
+type MockPlcConnection_Connect_Call struct {
+	*mock.Call
+}
+
+// Connect is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) Connect() *MockPlcConnection_Connect_Call {
+	return &MockPlcConnection_Connect_Call{Call: _e.mock.On("Connect")}
+}
+
+func (_c *MockPlcConnection_Connect_Call) Run(run func()) *MockPlcConnection_Connect_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_Connect_Call) Return(_a0 <-chan plc4go.PlcConnectionConnectResult) *MockPlcConnection_Connect_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_Connect_Call) RunAndReturn(run func() <-chan plc4go.PlcConnectionConnectResult) *MockPlcConnection_Connect_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// ConnectWithContext provides a mock function with given fields: ctx
+func (_m *MockPlcConnection) ConnectWithContext(ctx context.Context) <-chan plc4go.PlcConnectionConnectResult {
+	ret := _m.Called(ctx)
+
+	var r0 <-chan plc4go.PlcConnectionConnectResult
+	if rf, ok := ret.Get(0).(func(context.Context) <-chan plc4go.PlcConnectionConnectResult); ok {
+		r0 = rf(ctx)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(<-chan plc4go.PlcConnectionConnectResult)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_ConnectWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConnectWithContext'
+type MockPlcConnection_ConnectWithContext_Call struct {
+	*mock.Call
+}
+
+// ConnectWithContext is a helper method to define mock.On call
+//   - ctx context.Context
+func (_e *MockPlcConnection_Expecter) ConnectWithContext(ctx interface{}) *MockPlcConnection_ConnectWithContext_Call {
+	return &MockPlcConnection_ConnectWithContext_Call{Call: _e.mock.On("ConnectWithContext", ctx)}
+}
+
+func (_c *MockPlcConnection_ConnectWithContext_Call) Run(run func(ctx context.Context)) *MockPlcConnection_ConnectWithContext_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context))
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_ConnectWithContext_Call) Return(_a0 <-chan plc4go.PlcConnectionConnectResult) *MockPlcConnection_ConnectWithContext_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_ConnectWithContext_Call) RunAndReturn(run func(context.Context) <-chan plc4go.PlcConnectionConnectResult) *MockPlcConnection_ConnectWithContext_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// GetMetadata provides a mock function with given fields:
+func (_m *MockPlcConnection) GetMetadata() model.PlcConnectionMetadata {
+	ret := _m.Called()
+
+	var r0 model.PlcConnectionMetadata
+	if rf, ok := ret.Get(0).(func() model.PlcConnectionMetadata); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(model.PlcConnectionMetadata)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_GetMetadata_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetMetadata'
+type MockPlcConnection_GetMetadata_Call struct {
+	*mock.Call
+}
+
+// GetMetadata is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) GetMetadata() *MockPlcConnection_GetMetadata_Call {
+	return &MockPlcConnection_GetMetadata_Call{Call: _e.mock.On("GetMetadata")}
+}
+
+func (_c *MockPlcConnection_GetMetadata_Call) Run(run func()) *MockPlcConnection_GetMetadata_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_GetMetadata_Call) Return(_a0 model.PlcConnectionMetadata) *MockPlcConnection_GetMetadata_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_GetMetadata_Call) RunAndReturn(run func() model.PlcConnectionMetadata) *MockPlcConnection_GetMetadata_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// IsConnected provides a mock function with given fields:
+func (_m *MockPlcConnection) IsConnected() bool {
+	ret := _m.Called()
+
+	var r0 bool
+	if rf, ok := ret.Get(0).(func() bool); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(bool)
+	}
+
+	return r0
+}
+
+// MockPlcConnection_IsConnected_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsConnected'
+type MockPlcConnection_IsConnected_Call struct {
+	*mock.Call
+}
+
+// IsConnected is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) IsConnected() *MockPlcConnection_IsConnected_Call {
+	return &MockPlcConnection_IsConnected_Call{Call: _e.mock.On("IsConnected")}
+}
+
+func (_c *MockPlcConnection_IsConnected_Call) Run(run func()) *MockPlcConnection_IsConnected_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_IsConnected_Call) Return(_a0 bool) *MockPlcConnection_IsConnected_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_IsConnected_Call) RunAndReturn(run func() bool) *MockPlcConnection_IsConnected_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Ping provides a mock function with given fields:
+func (_m *MockPlcConnection) Ping() <-chan plc4go.PlcConnectionPingResult {
+	ret := _m.Called()
+
+	var r0 <-chan plc4go.PlcConnectionPingResult
+	if rf, ok := ret.Get(0).(func() <-chan plc4go.PlcConnectionPingResult); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(<-chan plc4go.PlcConnectionPingResult)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_Ping_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ping'
+type MockPlcConnection_Ping_Call struct {
+	*mock.Call
+}
+
+// Ping is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) Ping() *MockPlcConnection_Ping_Call {
+	return &MockPlcConnection_Ping_Call{Call: _e.mock.On("Ping")}
+}
+
+func (_c *MockPlcConnection_Ping_Call) Run(run func()) *MockPlcConnection_Ping_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_Ping_Call) Return(_a0 <-chan plc4go.PlcConnectionPingResult) *MockPlcConnection_Ping_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_Ping_Call) RunAndReturn(run func() <-chan plc4go.PlcConnectionPingResult) *MockPlcConnection_Ping_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// ReadRequestBuilder provides a mock function with given fields:
+func (_m *MockPlcConnection) ReadRequestBuilder() model.PlcReadRequestBuilder {
+	ret := _m.Called()
+
+	var r0 model.PlcReadRequestBuilder
+	if rf, ok := ret.Get(0).(func() model.PlcReadRequestBuilder); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(model.PlcReadRequestBuilder)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_ReadRequestBuilder_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReadRequestBuilder'
+type MockPlcConnection_ReadRequestBuilder_Call struct {
+	*mock.Call
+}
+
+// ReadRequestBuilder is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) ReadRequestBuilder() *MockPlcConnection_ReadRequestBuilder_Call {
+	return &MockPlcConnection_ReadRequestBuilder_Call{Call: _e.mock.On("ReadRequestBuilder")}
+}
+
+func (_c *MockPlcConnection_ReadRequestBuilder_Call) Run(run func()) *MockPlcConnection_ReadRequestBuilder_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_ReadRequestBuilder_Call) Return(_a0 model.PlcReadRequestBuilder) *MockPlcConnection_ReadRequestBuilder_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_ReadRequestBuilder_Call) RunAndReturn(run func() model.PlcReadRequestBuilder) *MockPlcConnection_ReadRequestBuilder_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// SubscriptionRequestBuilder provides a mock function with given fields:
+func (_m *MockPlcConnection) SubscriptionRequestBuilder() model.PlcSubscriptionRequestBuilder {
+	ret := _m.Called()
+
+	var r0 model.PlcSubscriptionRequestBuilder
+	if rf, ok := ret.Get(0).(func() model.PlcSubscriptionRequestBuilder); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(model.PlcSubscriptionRequestBuilder)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_SubscriptionRequestBuilder_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SubscriptionRequestBuilder'
+type MockPlcConnection_SubscriptionRequestBuilder_Call struct {
+	*mock.Call
+}
+
+// SubscriptionRequestBuilder is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) SubscriptionRequestBuilder() *MockPlcConnection_SubscriptionRequestBuilder_Call {
+	return &MockPlcConnection_SubscriptionRequestBuilder_Call{Call: _e.mock.On("SubscriptionRequestBuilder")}
+}
+
+func (_c *MockPlcConnection_SubscriptionRequestBuilder_Call) Run(run func()) *MockPlcConnection_SubscriptionRequestBuilder_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_SubscriptionRequestBuilder_Call) Return(_a0 model.PlcSubscriptionRequestBuilder) *MockPlcConnection_SubscriptionRequestBuilder_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_SubscriptionRequestBuilder_Call) RunAndReturn(run func() model.PlcSubscriptionRequestBuilder) *MockPlcConnection_SubscriptionRequestBuilder_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// UnsubscriptionRequestBuilder provides a mock function with given fields:
+func (_m *MockPlcConnection) UnsubscriptionRequestBuilder() model.PlcUnsubscriptionRequestBuilder {
+	ret := _m.Called()
+
+	var r0 model.PlcUnsubscriptionRequestBuilder
+	if rf, ok := ret.Get(0).(func() model.PlcUnsubscriptionRequestBuilder); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(model.PlcUnsubscriptionRequestBuilder)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_UnsubscriptionRequestBuilder_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UnsubscriptionRequestBuilder'
+type MockPlcConnection_UnsubscriptionRequestBuilder_Call struct {
+	*mock.Call
+}
+
+// UnsubscriptionRequestBuilder is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) UnsubscriptionRequestBuilder() *MockPlcConnection_UnsubscriptionRequestBuilder_Call {
+	return &MockPlcConnection_UnsubscriptionRequestBuilder_Call{Call: _e.mock.On("UnsubscriptionRequestBuilder")}
+}
+
+func (_c *MockPlcConnection_UnsubscriptionRequestBuilder_Call) Run(run func()) *MockPlcConnection_UnsubscriptionRequestBuilder_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_UnsubscriptionRequestBuilder_Call) Return(_a0 model.PlcUnsubscriptionRequestBuilder) *MockPlcConnection_UnsubscriptionRequestBuilder_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_UnsubscriptionRequestBuilder_Call) RunAndReturn(run func() model.PlcUnsubscriptionRequestBuilder) *MockPlcConnection_UnsubscriptionRequestBuilder_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// WriteRequestBuilder provides a mock function with given fields:
+func (_m *MockPlcConnection) WriteRequestBuilder() model.PlcWriteRequestBuilder {
+	ret := _m.Called()
+
+	var r0 model.PlcWriteRequestBuilder
+	if rf, ok := ret.Get(0).(func() model.PlcWriteRequestBuilder); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(model.PlcWriteRequestBuilder)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcConnection_WriteRequestBuilder_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteRequestBuilder'
+type MockPlcConnection_WriteRequestBuilder_Call struct {
+	*mock.Call
+}
+
+// WriteRequestBuilder is a helper method to define mock.On call
+func (_e *MockPlcConnection_Expecter) WriteRequestBuilder() *MockPlcConnection_WriteRequestBuilder_Call {
+	return &MockPlcConnection_WriteRequestBuilder_Call{Call: _e.mock.On("WriteRequestBuilder")}
+}
+
+func (_c *MockPlcConnection_WriteRequestBuilder_Call) Run(run func()) *MockPlcConnection_WriteRequestBuilder_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcConnection_WriteRequestBuilder_Call) Return(_a0 model.PlcWriteRequestBuilder) *MockPlcConnection_WriteRequestBuilder_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcConnection_WriteRequestBuilder_Call) RunAndReturn(run func() model.PlcWriteRequestBuilder) *MockPlcConnection_WriteRequestBuilder_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockPlcConnection interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockPlcConnection creates a new instance of MockPlcConnection. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockPlcConnection(t mockConstructorTestingTNewMockPlcConnection) *MockPlcConnection {
+	mock := &MockPlcConnection{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/default/mock_PlcQuery_test.go b/plc4go/spi/default/mock_PlcQuery_test.go
new file mode 100644
index 0000000000..ecd9e996ab
--- /dev/null
+++ b/plc4go/spi/default/mock_PlcQuery_test.go
@@ -0,0 +1,93 @@
+/*
+ * 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
+ *
+ *   https://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.
+ */
+
+// Code generated by mockery v2.26.1. DO NOT EDIT.
+
+package _default
+
+import mock "github.com/stretchr/testify/mock"
+
+// MockPlcQuery is an autogenerated mock type for the PlcQuery type
+type MockPlcQuery struct {
+	mock.Mock
+}
+
+type MockPlcQuery_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockPlcQuery) EXPECT() *MockPlcQuery_Expecter {
+	return &MockPlcQuery_Expecter{mock: &_m.Mock}
+}
+
+// GetQueryString provides a mock function with given fields:
+func (_m *MockPlcQuery) GetQueryString() string {
+	ret := _m.Called()
+
+	var r0 string
+	if rf, ok := ret.Get(0).(func() string); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(string)
+	}
+
+	return r0
+}
+
+// MockPlcQuery_GetQueryString_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetQueryString'
+type MockPlcQuery_GetQueryString_Call struct {
+	*mock.Call
+}
+
+// GetQueryString is a helper method to define mock.On call
+func (_e *MockPlcQuery_Expecter) GetQueryString() *MockPlcQuery_GetQueryString_Call {
+	return &MockPlcQuery_GetQueryString_Call{Call: _e.mock.On("GetQueryString")}
+}
+
+func (_c *MockPlcQuery_GetQueryString_Call) Run(run func()) *MockPlcQuery_GetQueryString_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockPlcQuery_GetQueryString_Call) Return(_a0 string) *MockPlcQuery_GetQueryString_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcQuery_GetQueryString_Call) RunAndReturn(run func() string) *MockPlcQuery_GetQueryString_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockPlcQuery interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockPlcQuery creates a new instance of MockPlcQuery. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockPlcQuery(t mockConstructorTestingTNewMockPlcQuery) *MockPlcQuery {
+	mock := &MockPlcQuery{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/default/mock_PlcTagHandler_test.go b/plc4go/spi/default/mock_PlcTagHandler_test.go
new file mode 100644
index 0000000000..ac6c7388a6
--- /dev/null
+++ b/plc4go/spi/default/mock_PlcTagHandler_test.go
@@ -0,0 +1,163 @@
+/*
+ * 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
+ *
+ *   https://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.
+ */
+
+// Code generated by mockery v2.26.1. DO NOT EDIT.
+
+package _default
+
+import (
+	model "github.com/apache/plc4x/plc4go/pkg/api/model"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// MockPlcTagHandler is an autogenerated mock type for the PlcTagHandler type
+type MockPlcTagHandler struct {
+	mock.Mock
+}
+
+type MockPlcTagHandler_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockPlcTagHandler) EXPECT() *MockPlcTagHandler_Expecter {
+	return &MockPlcTagHandler_Expecter{mock: &_m.Mock}
+}
+
+// ParseQuery provides a mock function with given fields: query
+func (_m *MockPlcTagHandler) ParseQuery(query string) (model.PlcQuery, error) {
+	ret := _m.Called(query)
+
+	var r0 model.PlcQuery
+	var r1 error
+	if rf, ok := ret.Get(0).(func(string) (model.PlcQuery, error)); ok {
+		return rf(query)
+	}
+	if rf, ok := ret.Get(0).(func(string) model.PlcQuery); ok {
+		r0 = rf(query)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(model.PlcQuery)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(string) error); ok {
+		r1 = rf(query)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MockPlcTagHandler_ParseQuery_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseQuery'
+type MockPlcTagHandler_ParseQuery_Call struct {
+	*mock.Call
+}
+
+// ParseQuery is a helper method to define mock.On call
+//   - query string
+func (_e *MockPlcTagHandler_Expecter) ParseQuery(query interface{}) *MockPlcTagHandler_ParseQuery_Call {
+	return &MockPlcTagHandler_ParseQuery_Call{Call: _e.mock.On("ParseQuery", query)}
+}
+
+func (_c *MockPlcTagHandler_ParseQuery_Call) Run(run func(query string)) *MockPlcTagHandler_ParseQuery_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(string))
+	})
+	return _c
+}
+
+func (_c *MockPlcTagHandler_ParseQuery_Call) Return(_a0 model.PlcQuery, _a1 error) *MockPlcTagHandler_ParseQuery_Call {
+	_c.Call.Return(_a0, _a1)
+	return _c
+}
+
+func (_c *MockPlcTagHandler_ParseQuery_Call) RunAndReturn(run func(string) (model.PlcQuery, error)) *MockPlcTagHandler_ParseQuery_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// ParseTag provides a mock function with given fields: tagAddress
+func (_m *MockPlcTagHandler) ParseTag(tagAddress string) (model.PlcTag, error) {
+	ret := _m.Called(tagAddress)
+
+	var r0 model.PlcTag
+	var r1 error
+	if rf, ok := ret.Get(0).(func(string) (model.PlcTag, error)); ok {
+		return rf(tagAddress)
+	}
+	if rf, ok := ret.Get(0).(func(string) model.PlcTag); ok {
+		r0 = rf(tagAddress)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(model.PlcTag)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(string) error); ok {
+		r1 = rf(tagAddress)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MockPlcTagHandler_ParseTag_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTag'
+type MockPlcTagHandler_ParseTag_Call struct {
+	*mock.Call
+}
+
+// ParseTag is a helper method to define mock.On call
+//   - tagAddress string
+func (_e *MockPlcTagHandler_Expecter) ParseTag(tagAddress interface{}) *MockPlcTagHandler_ParseTag_Call {
+	return &MockPlcTagHandler_ParseTag_Call{Call: _e.mock.On("ParseTag", tagAddress)}
+}
+
+func (_c *MockPlcTagHandler_ParseTag_Call) Run(run func(tagAddress string)) *MockPlcTagHandler_ParseTag_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(string))
+	})
+	return _c
+}
+
+func (_c *MockPlcTagHandler_ParseTag_Call) Return(_a0 model.PlcTag, _a1 error) *MockPlcTagHandler_ParseTag_Call {
+	_c.Call.Return(_a0, _a1)
+	return _c
+}
+
+func (_c *MockPlcTagHandler_ParseTag_Call) RunAndReturn(run func(string) (model.PlcTag, error)) *MockPlcTagHandler_ParseTag_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockPlcTagHandler interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockPlcTagHandler creates a new instance of MockPlcTagHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockPlcTagHandler(t mockConstructorTestingTNewMockPlcTagHandler) *MockPlcTagHandler {
+	mock := &MockPlcTagHandler{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/default/mock_TransportInstance_test.go b/plc4go/spi/default/mock_TransportInstance_test.go
new file mode 100644
index 0000000000..04f1eae423
--- /dev/null
+++ b/plc4go/spi/default/mock_TransportInstance_test.go
@@ -0,0 +1,506 @@
+/*
+ * 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
+ *
+ *   https://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.
+ */
+
+// Code generated by mockery v2.26.1. DO NOT EDIT.
+
+package _default
+
+import (
+	bufio "bufio"
+	context "context"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// MockTransportInstance is an autogenerated mock type for the TransportInstance type
+type MockTransportInstance struct {
+	mock.Mock
+}
+
+type MockTransportInstance_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockTransportInstance) EXPECT() *MockTransportInstance_Expecter {
+	return &MockTransportInstance_Expecter{mock: &_m.Mock}
+}
+
+// Close provides a mock function with given fields:
+func (_m *MockTransportInstance) Close() error {
+	ret := _m.Called()
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func() error); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockTransportInstance_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
+type MockTransportInstance_Close_Call struct {
+	*mock.Call
+}
+
+// Close is a helper method to define mock.On call
+func (_e *MockTransportInstance_Expecter) Close() *MockTransportInstance_Close_Call {
+	return &MockTransportInstance_Close_Call{Call: _e.mock.On("Close")}
+}
+
+func (_c *MockTransportInstance_Close_Call) Run(run func()) *MockTransportInstance_Close_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_Close_Call) Return(_a0 error) *MockTransportInstance_Close_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockTransportInstance_Close_Call) RunAndReturn(run func() error) *MockTransportInstance_Close_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Connect provides a mock function with given fields:
+func (_m *MockTransportInstance) Connect() error {
+	ret := _m.Called()
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func() error); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockTransportInstance_Connect_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Connect'
+type MockTransportInstance_Connect_Call struct {
+	*mock.Call
+}
+
+// Connect is a helper method to define mock.On call
+func (_e *MockTransportInstance_Expecter) Connect() *MockTransportInstance_Connect_Call {
+	return &MockTransportInstance_Connect_Call{Call: _e.mock.On("Connect")}
+}
+
+func (_c *MockTransportInstance_Connect_Call) Run(run func()) *MockTransportInstance_Connect_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_Connect_Call) Return(_a0 error) *MockTransportInstance_Connect_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockTransportInstance_Connect_Call) RunAndReturn(run func() error) *MockTransportInstance_Connect_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// ConnectWithContext provides a mock function with given fields: ctx
+func (_m *MockTransportInstance) ConnectWithContext(ctx context.Context) error {
+	ret := _m.Called(ctx)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(context.Context) error); ok {
+		r0 = rf(ctx)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockTransportInstance_ConnectWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConnectWithContext'
+type MockTransportInstance_ConnectWithContext_Call struct {
+	*mock.Call
+}
+
+// ConnectWithContext is a helper method to define mock.On call
+//   - ctx context.Context
+func (_e *MockTransportInstance_Expecter) ConnectWithContext(ctx interface{}) *MockTransportInstance_ConnectWithContext_Call {
+	return &MockTransportInstance_ConnectWithContext_Call{Call: _e.mock.On("ConnectWithContext", ctx)}
+}
+
+func (_c *MockTransportInstance_ConnectWithContext_Call) Run(run func(ctx context.Context)) *MockTransportInstance_ConnectWithContext_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context))
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_ConnectWithContext_Call) Return(_a0 error) *MockTransportInstance_ConnectWithContext_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockTransportInstance_ConnectWithContext_Call) RunAndReturn(run func(context.Context) error) *MockTransportInstance_ConnectWithContext_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// FillBuffer provides a mock function with given fields: until
+func (_m *MockTransportInstance) FillBuffer(until func(uint, byte, *bufio.Reader) bool) error {
+	ret := _m.Called(until)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(func(uint, byte, *bufio.Reader) bool) error); ok {
+		r0 = rf(until)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockTransportInstance_FillBuffer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FillBuffer'
+type MockTransportInstance_FillBuffer_Call struct {
+	*mock.Call
+}
+
+// FillBuffer is a helper method to define mock.On call
+//   - until func(uint , byte , *bufio.Reader) bool
+func (_e *MockTransportInstance_Expecter) FillBuffer(until interface{}) *MockTransportInstance_FillBuffer_Call {
+	return &MockTransportInstance_FillBuffer_Call{Call: _e.mock.On("FillBuffer", until)}
+}
+
+func (_c *MockTransportInstance_FillBuffer_Call) Run(run func(until func(uint, byte, *bufio.Reader) bool)) *MockTransportInstance_FillBuffer_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(func(uint, byte, *bufio.Reader) bool))
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_FillBuffer_Call) Return(_a0 error) *MockTransportInstance_FillBuffer_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockTransportInstance_FillBuffer_Call) RunAndReturn(run func(func(uint, byte, *bufio.Reader) bool) error) *MockTransportInstance_FillBuffer_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// GetNumBytesAvailableInBuffer provides a mock function with given fields:
+func (_m *MockTransportInstance) GetNumBytesAvailableInBuffer() (uint32, error) {
+	ret := _m.Called()
+
+	var r0 uint32
+	var r1 error
+	if rf, ok := ret.Get(0).(func() (uint32, error)); ok {
+		return rf()
+	}
+	if rf, ok := ret.Get(0).(func() uint32); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(uint32)
+	}
+
+	if rf, ok := ret.Get(1).(func() error); ok {
+		r1 = rf()
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MockTransportInstance_GetNumBytesAvailableInBuffer_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetNumBytesAvailableInBuffer'
+type MockTransportInstance_GetNumBytesAvailableInBuffer_Call struct {
+	*mock.Call
+}
+
+// GetNumBytesAvailableInBuffer is a helper method to define mock.On call
+func (_e *MockTransportInstance_Expecter) GetNumBytesAvailableInBuffer() *MockTransportInstance_GetNumBytesAvailableInBuffer_Call {
+	return &MockTransportInstance_GetNumBytesAvailableInBuffer_Call{Call: _e.mock.On("GetNumBytesAvailableInBuffer")}
+}
+
+func (_c *MockTransportInstance_GetNumBytesAvailableInBuffer_Call) Run(run func()) *MockTransportInstance_GetNumBytesAvailableInBuffer_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_GetNumBytesAvailableInBuffer_Call) Return(_a0 uint32, _a1 error) *MockTransportInstance_GetNumBytesAvailableInBuffer_Call {
+	_c.Call.Return(_a0, _a1)
+	return _c
+}
+
+func (_c *MockTransportInstance_GetNumBytesAvailableInBuffer_Call) RunAndReturn(run func() (uint32, error)) *MockTransportInstance_GetNumBytesAvailableInBuffer_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// IsConnected provides a mock function with given fields:
+func (_m *MockTransportInstance) IsConnected() bool {
+	ret := _m.Called()
+
+	var r0 bool
+	if rf, ok := ret.Get(0).(func() bool); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(bool)
+	}
+
+	return r0
+}
+
+// MockTransportInstance_IsConnected_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IsConnected'
+type MockTransportInstance_IsConnected_Call struct {
+	*mock.Call
+}
+
+// IsConnected is a helper method to define mock.On call
+func (_e *MockTransportInstance_Expecter) IsConnected() *MockTransportInstance_IsConnected_Call {
+	return &MockTransportInstance_IsConnected_Call{Call: _e.mock.On("IsConnected")}
+}
+
+func (_c *MockTransportInstance_IsConnected_Call) Run(run func()) *MockTransportInstance_IsConnected_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_IsConnected_Call) Return(_a0 bool) *MockTransportInstance_IsConnected_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockTransportInstance_IsConnected_Call) RunAndReturn(run func() bool) *MockTransportInstance_IsConnected_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// PeekReadableBytes provides a mock function with given fields: numBytes
+func (_m *MockTransportInstance) PeekReadableBytes(numBytes uint32) ([]byte, error) {
+	ret := _m.Called(numBytes)
+
+	var r0 []byte
+	var r1 error
+	if rf, ok := ret.Get(0).(func(uint32) ([]byte, error)); ok {
+		return rf(numBytes)
+	}
+	if rf, ok := ret.Get(0).(func(uint32) []byte); ok {
+		r0 = rf(numBytes)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]byte)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(uint32) error); ok {
+		r1 = rf(numBytes)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MockTransportInstance_PeekReadableBytes_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'PeekReadableBytes'
+type MockTransportInstance_PeekReadableBytes_Call struct {
+	*mock.Call
+}
+
+// PeekReadableBytes is a helper method to define mock.On call
+//   - numBytes uint32
+func (_e *MockTransportInstance_Expecter) PeekReadableBytes(numBytes interface{}) *MockTransportInstance_PeekReadableBytes_Call {
+	return &MockTransportInstance_PeekReadableBytes_Call{Call: _e.mock.On("PeekReadableBytes", numBytes)}
+}
+
+func (_c *MockTransportInstance_PeekReadableBytes_Call) Run(run func(numBytes uint32)) *MockTransportInstance_PeekReadableBytes_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(uint32))
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_PeekReadableBytes_Call) Return(_a0 []byte, _a1 error) *MockTransportInstance_PeekReadableBytes_Call {
+	_c.Call.Return(_a0, _a1)
+	return _c
+}
+
+func (_c *MockTransportInstance_PeekReadableBytes_Call) RunAndReturn(run func(uint32) ([]byte, error)) *MockTransportInstance_PeekReadableBytes_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Read provides a mock function with given fields: numBytes
+func (_m *MockTransportInstance) Read(numBytes uint32) ([]byte, error) {
+	ret := _m.Called(numBytes)
+
+	var r0 []byte
+	var r1 error
+	if rf, ok := ret.Get(0).(func(uint32) ([]byte, error)); ok {
+		return rf(numBytes)
+	}
+	if rf, ok := ret.Get(0).(func(uint32) []byte); ok {
+		r0 = rf(numBytes)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]byte)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(uint32) error); ok {
+		r1 = rf(numBytes)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MockTransportInstance_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read'
+type MockTransportInstance_Read_Call struct {
+	*mock.Call
+}
+
+// Read is a helper method to define mock.On call
+//   - numBytes uint32
+func (_e *MockTransportInstance_Expecter) Read(numBytes interface{}) *MockTransportInstance_Read_Call {
+	return &MockTransportInstance_Read_Call{Call: _e.mock.On("Read", numBytes)}
+}
+
+func (_c *MockTransportInstance_Read_Call) Run(run func(numBytes uint32)) *MockTransportInstance_Read_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(uint32))
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_Read_Call) Return(_a0 []byte, _a1 error) *MockTransportInstance_Read_Call {
+	_c.Call.Return(_a0, _a1)
+	return _c
+}
+
+func (_c *MockTransportInstance_Read_Call) RunAndReturn(run func(uint32) ([]byte, error)) *MockTransportInstance_Read_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// String provides a mock function with given fields:
+func (_m *MockTransportInstance) String() string {
+	ret := _m.Called()
+
+	var r0 string
+	if rf, ok := ret.Get(0).(func() string); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(string)
+	}
+
+	return r0
+}
+
+// MockTransportInstance_String_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'String'
+type MockTransportInstance_String_Call struct {
+	*mock.Call
+}
+
+// String is a helper method to define mock.On call
+func (_e *MockTransportInstance_Expecter) String() *MockTransportInstance_String_Call {
+	return &MockTransportInstance_String_Call{Call: _e.mock.On("String")}
+}
+
+func (_c *MockTransportInstance_String_Call) Run(run func()) *MockTransportInstance_String_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run()
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_String_Call) Return(_a0 string) *MockTransportInstance_String_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockTransportInstance_String_Call) RunAndReturn(run func() string) *MockTransportInstance_String_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// Write provides a mock function with given fields: data
+func (_m *MockTransportInstance) Write(data []byte) error {
+	ret := _m.Called(data)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func([]byte) error); ok {
+		r0 = rf(data)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// MockTransportInstance_Write_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Write'
+type MockTransportInstance_Write_Call struct {
+	*mock.Call
+}
+
+// Write is a helper method to define mock.On call
+//   - data []byte
+func (_e *MockTransportInstance_Expecter) Write(data interface{}) *MockTransportInstance_Write_Call {
+	return &MockTransportInstance_Write_Call{Call: _e.mock.On("Write", data)}
+}
+
+func (_c *MockTransportInstance_Write_Call) Run(run func(data []byte)) *MockTransportInstance_Write_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].([]byte))
+	})
+	return _c
+}
+
+func (_c *MockTransportInstance_Write_Call) Return(_a0 error) *MockTransportInstance_Write_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockTransportInstance_Write_Call) RunAndReturn(run func([]byte) error) *MockTransportInstance_Write_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockTransportInstance interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockTransportInstance creates a new instance of MockTransportInstance. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockTransportInstance(t mockConstructorTestingTNewMockTransportInstance) *MockTransportInstance {
+	mock := &MockTransportInstance{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/default/testDriver_test.go b/plc4go/spi/default/mock_requirements.go
similarity index 53%
rename from plc4go/spi/default/testDriver_test.go
rename to plc4go/spi/default/mock_requirements.go
index c2a347a627..315be18e86 100644
--- a/plc4go/spi/default/testDriver_test.go
+++ b/plc4go/spi/default/mock_requirements.go
@@ -20,23 +20,46 @@
 package _default
 
 import (
-	"context"
-	"net/url"
-
 	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
 	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
-	"github.com/apache/plc4x/plc4go/spi/options"
+	"github.com/apache/plc4x/plc4go/spi"
 	"github.com/apache/plc4x/plc4go/spi/transports"
 )
 
-// TODO: replace with proper mock
-type testDriver struct {
+// Note this file is a Helper for mockery to generate use mocks from other package
+
+// Deprecated: don't use it in productive code
+type PlcConnection interface {
+	plc4go.PlcConnection
+}
+
+// Deprecated: don't use it in productive code
+type Message interface {
+	spi.Message
+}
+
+// Deprecated: don't use it in productive code
+type MessageCodec interface {
+	spi.MessageCodec
+	spi.TransportInstanceExposer
+}
+
+// Deprecated: don't use it in productive code
+type PlcQuery interface {
+	apiModel.PlcQuery
+}
+
+// Deprecated: don't use it in productive code
+type PlcTagHandler interface {
+	spi.PlcTagHandler
 }
 
-func (testDriver) GetConnectionWithContext(ctx context.Context, transportUrl url.URL, transports map[string]transports.Transport, options map[string][]string) <-chan plc4go.PlcConnectionConnectResult {
-	return nil
+// Deprecated: don't use it in productive code
+type TransportInstance interface {
+	transports.TransportInstance
 }
 
-func (testDriver) DiscoverWithContext(callback context.Context, event func(event apiModel.PlcDiscoveryItem), discoveryOptions ...options.WithDiscoveryOption) error {
-	return nil
+// Deprecated: don't use it in productive code
+type PlcConnectionConnectResult interface {
+	plc4go.PlcConnectionConnectResult
 }
diff --git a/plc4go/spi/default/testBrowser_test.go b/plc4go/spi/default/testBrowser_test.go
deleted file mode 100644
index ad1fe971d5..0000000000
--- a/plc4go/spi/default/testBrowser_test.go
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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
- *
- *   https://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 _default
-
-import (
-	"context"
-
-	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
-)
-
-// TODO: replace with proper mock
-type testBrowser struct {
-	dispatcher func(ctx context.Context, interceptor func(result apiModel.PlcBrowseItem) bool, queryName string, query apiModel.PlcQuery) (apiModel.PlcResponseCode, []apiModel.PlcBrowseItem)
-}
-
-func (t testBrowser) BrowseQuery(ctx context.Context, interceptor func(result apiModel.PlcBrowseItem) bool, queryName string, query apiModel.PlcQuery) (apiModel.PlcResponseCode, []apiModel.PlcBrowseItem) {
-	if t.dispatcher != nil {
-		return t.dispatcher(ctx, interceptor, queryName, query)
-	}
-	interceptor(nil)
-	return apiModel.PlcResponseCode_OK, nil
-}
diff --git a/plc4go/spi/default/testConnection_test.go b/plc4go/spi/default/testConnection_test.go
deleted file mode 100644
index 66a36a6b75..0000000000
--- a/plc4go/spi/default/testConnection_test.go
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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
- *
- *   https://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 _default
-
-import (
-	"context"
-	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
-	"github.com/apache/plc4x/plc4go/pkg/api/model"
-	"github.com/apache/plc4x/plc4go/spi"
-)
-
-// TODO: replace with proper mock
-type testConnection struct {
-	testMessageCodec testMessageCodec
-	connected        bool
-}
-
-func (t testConnection) Connect() <-chan plc4go.PlcConnectionConnectResult {
-	return t.ConnectWithContext(nil)
-}
-
-func (t testConnection) BlockingClose() {
-	// NO-OP
-}
-
-func (t testConnection) Close() <-chan plc4go.PlcConnectionCloseResult {
-	// NO-OP
-	return nil
-}
-
-func (t testConnection) IsConnected() bool {
-	return t.connected
-}
-
-func (t testConnection) Ping() <-chan plc4go.PlcConnectionPingResult {
-	// NO-OP
-	return nil
-}
-
-func (t testConnection) GetMetadata() model.PlcConnectionMetadata {
-	// NO-OP
-	return nil
-}
-
-func (t testConnection) ReadRequestBuilder() model.PlcReadRequestBuilder {
-	// NO-OP
-	return nil
-}
-
-func (t testConnection) WriteRequestBuilder() model.PlcWriteRequestBuilder {
-	// NO-OP
-	return nil
-}
-
-func (t testConnection) SubscriptionRequestBuilder() model.PlcSubscriptionRequestBuilder {
-	// NO-OP
-	return nil
-}
-
-func (t testConnection) UnsubscriptionRequestBuilder() model.PlcUnsubscriptionRequestBuilder {
-	// NO-OP
-	return nil
-}
-
-func (t testConnection) BrowseRequestBuilder() model.PlcBrowseRequestBuilder {
-	// NO-OP
-	return nil
-}
-
-func (t testConnection) GetConnection() plc4go.PlcConnection {
-	// NO-OP
-	return t
-}
-
-func (t testConnection) GetMessageCodec() spi.MessageCodec {
-	return t.testMessageCodec
-}
-
-func (t testConnection) ConnectWithContext(_ context.Context) <-chan plc4go.PlcConnectionConnectResult {
-	// NO-OP
-	return nil
-}
diff --git a/plc4go/spi/default/testMessageCodec_test.go b/plc4go/spi/default/testMessageCodec_test.go
deleted file mode 100644
index 000ef4286e..0000000000
--- a/plc4go/spi/default/testMessageCodec_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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
- *
- *   https://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 _default
-
-import (
-	"context"
-	"github.com/apache/plc4x/plc4go/spi/transports"
-
-	"github.com/apache/plc4x/plc4go/spi"
-	"time"
-)
-
-// TODO: replace with proper mock
-type testMessageCodec struct {
-	receive func() (spi.Message, error)
-	send    func(message spi.Message) error
-}
-
-func (t testMessageCodec) Connect() error {
-	// NO-OP
-	return nil
-}
-
-func (t testMessageCodec) ConnectWithContext(ctx context.Context) error {
-	// NO-OP
-	return nil
-}
-
-func (t testMessageCodec) Disconnect() error {
-	// NO-OP
-	return nil
-}
-
-func (t testMessageCodec) IsRunning() bool {
-	// NO-OP
-	return false
-}
-
-func (t testMessageCodec) Send(message spi.Message) error {
-	if t.send != nil {
-		return t.send(message)
-	}
-	// NO-OP
-	return nil
-}
-
-func (t testMessageCodec) Expect(ctx context.Context, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError, ttl time.Duration) error {
-	// NO-OP
-	return nil
-}
-
-func (t testMessageCodec) SendRequest(ctx context.Context, message spi.Message, acceptsMessage spi.AcceptsMessage, handleMessage spi.HandleMessage, handleError spi.HandleError, ttl time.Duration) error {
-	// NO-OP
-	return nil
-}
-
-func (t testMessageCodec) GetDefaultIncomingMessageChannel() chan spi.Message {
-	// NO-OP
-	return nil
-}
-
-func (t testMessageCodec) GetTransportInstance() transports.TransportInstance {
-	return testTransportInstance{}
-}
-
-func (t testMessageCodec) GetCodec() spi.MessageCodec {
-	return t
-}
-
-func (t testMessageCodec) Receive() (spi.Message, error) {
-	if t.receive != nil {
-		return t.receive()
-	}
-	// NO-OP
-	return nil, nil
-}
diff --git a/plc4go/spi/default/testMessage_test.go b/plc4go/spi/default/testMessage_test.go
deleted file mode 100644
index dd55c40013..0000000000
--- a/plc4go/spi/default/testMessage_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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
- *
- *   https://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 _default
-
-import (
-	"context"
-	"github.com/apache/plc4x/plc4go/spi/utils"
-)
-
-// TODO: replace with proper mock
-type testMessage struct {
-}
-
-func (testMessage) Serialize() ([]byte, error) {
-	// NO-OP
-	return nil, nil
-}
-
-func (testMessage) SerializeWithWriteBuffer(ctx context.Context, writeBuffer utils.WriteBuffer) error {
-	// NO-OP
-	return nil
-}
-
-func (testMessage) GetLengthInBytes(ctx context.Context) uint16 {
-	// NO-OP
-	return 0
-}
-
-func (testMessage) GetLengthInBits(ctx context.Context) uint16 {
-	// NO-OP
-	return 0
-}
diff --git a/plc4go/spi/default/testQuery_test.go b/plc4go/spi/default/testQuery_test.go
deleted file mode 100644
index f4605157fd..0000000000
--- a/plc4go/spi/default/testQuery_test.go
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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
- *
- *   https://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 _default
-
-// TODO: replace with proper mock
-type testQuery struct {
-}
-
-func (testQuery) GetQueryString() string {
-	return "blub"
-}
diff --git a/plc4go/spi/default/testTagHandler_test.go b/plc4go/spi/default/testTagHandler_test.go
deleted file mode 100644
index 2d0c0e0019..0000000000
--- a/plc4go/spi/default/testTagHandler_test.go
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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
- *
- *   https://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 _default
-
-import apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
-
-// TODO: replace with proper mock
-type testTagHandler struct {
-}
-
-func (testTagHandler) ParseTag(tagAddress string) (apiModel.PlcTag, error) {
-	return nil, nil
-}
-
-func (testTagHandler) ParseQuery(query string) (apiModel.PlcQuery, error) {
-	return nil, nil
-}
diff --git a/plc4go/spi/transports/TransportInstance.go b/plc4go/spi/transports/TransportInstance.go
index 34005e3c24..fc3b66d328 100644
--- a/plc4go/spi/transports/TransportInstance.go
+++ b/plc4go/spi/transports/TransportInstance.go
@@ -72,7 +72,7 @@ func (m *defaultBufferedTransportInstance) ConnectWithContext(ctx context.Contex
 	go func() {
 		defer func() {
 			if err := recover(); err != nil {
-				log.Fatal().Interface("err", err).Msg("connect panic-ed")
+				log.Error().Interface("err", err).Msg("connect panic-ed")
 			}
 		}()
 		ch <- m.Connect()
diff --git a/plc4go/spi/utils/Net.go b/plc4go/spi/utils/Net.go
index ec76328cdb..a166a21213 100644
--- a/plc4go/spi/utils/Net.go
+++ b/plc4go/spi/utils/Net.go
@@ -145,11 +145,10 @@ func lockupIpsUsingArp(ctx context.Context, netInterface net.Interface, ipNet *n
 				log.Trace().Msgf("Scheduling discovery for IP %s", ip)
 				timeout := time.NewTimer(2 * time.Second)
 				go func(ip net.IP) {
+					defer CleanupTimer(timeout)
 					select {
 					case <-ctx.Done():
-						CleanupTimer(timeout)
 					case foundIps <- DuplicateIP(ip):
-						CleanupTimer(timeout)
 					case <-timeout.C:
 					}
 				}(DuplicateIP(ip))
@@ -232,11 +231,10 @@ func lookupIps(ctx context.Context, ipnet *net.IPNet, foundIps chan net.IP, wg *
 		timeout := time.NewTimer(2 * time.Second)
 		go func(ip net.IP) {
 			defer func() { wg.Done() }()
+			defer CleanupTimer(timeout)
 			select {
 			case <-ctx.Done():
-				CleanupTimer(timeout)
 			case foundIps <- ip:
-				CleanupTimer(timeout)
 			case <-timeout.C:
 			}
 		}(DuplicateIP(ip))