/*
 * 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.28.2. DO NOT EDIT.

package interceptors

import (
	model "github.com/apache/plc4x/plc4go/pkg/api/model"
	mock "github.com/stretchr/testify/mock"
)

// mockWriteResponseFactory is an autogenerated mock type for the writeResponseFactory type
type mockWriteResponseFactory struct {
	mock.Mock
}

type mockWriteResponseFactory_Expecter struct {
	mock *mock.Mock
}

func (_m *mockWriteResponseFactory) EXPECT() *mockWriteResponseFactory_Expecter {
	return &mockWriteResponseFactory_Expecter{mock: &_m.Mock}
}

// Execute provides a mock function with given fields: request, responseCodes
func (_m *mockWriteResponseFactory) Execute(request model.PlcWriteRequest, responseCodes map[string]model.PlcResponseCode) model.PlcWriteResponse {
	ret := _m.Called(request, responseCodes)

	var r0 model.PlcWriteResponse
	if rf, ok := ret.Get(0).(func(model.PlcWriteRequest, map[string]model.PlcResponseCode) model.PlcWriteResponse); ok {
		r0 = rf(request, responseCodes)
	} else {
		if ret.Get(0) != nil {
			r0 = ret.Get(0).(model.PlcWriteResponse)
		}
	}

	return r0
}

// mockWriteResponseFactory_Execute_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Execute'
type mockWriteResponseFactory_Execute_Call struct {
	*mock.Call
}

// Execute is a helper method to define mock.On call
//   - request model.PlcWriteRequest
//   - responseCodes map[string]model.PlcResponseCode
func (_e *mockWriteResponseFactory_Expecter) Execute(request interface{}, responseCodes interface{}) *mockWriteResponseFactory_Execute_Call {
	return &mockWriteResponseFactory_Execute_Call{Call: _e.mock.On("Execute", request, responseCodes)}
}

func (_c *mockWriteResponseFactory_Execute_Call) Run(run func(request model.PlcWriteRequest, responseCodes map[string]model.PlcResponseCode)) *mockWriteResponseFactory_Execute_Call {
	_c.Call.Run(func(args mock.Arguments) {
		run(args[0].(model.PlcWriteRequest), args[1].(map[string]model.PlcResponseCode))
	})
	return _c
}

func (_c *mockWriteResponseFactory_Execute_Call) Return(_a0 model.PlcWriteResponse) *mockWriteResponseFactory_Execute_Call {
	_c.Call.Return(_a0)
	return _c
}

func (_c *mockWriteResponseFactory_Execute_Call) RunAndReturn(run func(model.PlcWriteRequest, map[string]model.PlcResponseCode) model.PlcWriteResponse) *mockWriteResponseFactory_Execute_Call {
	_c.Call.Return(run)
	return _c
}

type mockConstructorTestingTnewMockWriteResponseFactory interface {
	mock.TestingT
	Cleanup(func())
}

// newMockWriteResponseFactory creates a new instance of mockWriteResponseFactory. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
func newMockWriteResponseFactory(t mockConstructorTestingTnewMockWriteResponseFactory) *mockWriteResponseFactory {
	mock := &mockWriteResponseFactory{}
	mock.Mock.Test(t)

	t.Cleanup(func() { mock.AssertExpectations(t) })

	return mock
}
