// Code generated by MockGen. DO NOT EDIT.
// Source: server_test.go

// Package http is a generated GoMock package.
package http

import (
	http "net/http"
	reflect "reflect"

	gomock "github.com/golang/mock/gomock"
)

// MockHttpServerCallback is a mock of HttpServerCallback interface.
type MockHttpServerCallback struct {
	ctrl     *gomock.Controller
	recorder *MockHttpServerCallbackMockRecorder
}

// MockHttpServerCallbackMockRecorder is the mock recorder for MockHttpServerCallback.
type MockHttpServerCallbackMockRecorder struct {
	mock *MockHttpServerCallback
}

// NewMockHttpServerCallback creates a new mock instance.
func NewMockHttpServerCallback(ctrl *gomock.Controller) *MockHttpServerCallback {
	mock := &MockHttpServerCallback{ctrl: ctrl}
	mock.recorder = &MockHttpServerCallbackMockRecorder{mock}
	return mock
}

// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockHttpServerCallback) EXPECT() *MockHttpServerCallbackMockRecorder {
	return m.recorder
}

// StateDELETE mocks base method.
func (m *MockHttpServerCallback) StateDELETE(req *http.Request) {
	m.ctrl.T.Helper()
	m.ctrl.Call(m, "StateDELETE", req)
}

// StateDELETE indicates an expected call of StateDELETE.
func (mr *MockHttpServerCallbackMockRecorder) StateDELETE(req interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateDELETE", reflect.TypeOf((*MockHttpServerCallback)(nil).StateDELETE), req)
}

// StateGET mocks base method.
func (m *MockHttpServerCallback) StateGET(req *http.Request) {
	m.ctrl.T.Helper()
	m.ctrl.Call(m, "StateGET", req)
}

// StateGET indicates an expected call of StateGET.
func (mr *MockHttpServerCallbackMockRecorder) StateGET(req interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateGET", reflect.TypeOf((*MockHttpServerCallback)(nil).StateGET), req)
}

// StateLOCK mocks base method.
func (m *MockHttpServerCallback) StateLOCK(req *http.Request) {
	m.ctrl.T.Helper()
	m.ctrl.Call(m, "StateLOCK", req)
}

// StateLOCK indicates an expected call of StateLOCK.
func (mr *MockHttpServerCallbackMockRecorder) StateLOCK(req interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateLOCK", reflect.TypeOf((*MockHttpServerCallback)(nil).StateLOCK), req)
}

// StatePOST mocks base method.
func (m *MockHttpServerCallback) StatePOST(req *http.Request) {
	m.ctrl.T.Helper()
	m.ctrl.Call(m, "StatePOST", req)
}

// StatePOST indicates an expected call of StatePOST.
func (mr *MockHttpServerCallbackMockRecorder) StatePOST(req interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StatePOST", reflect.TypeOf((*MockHttpServerCallback)(nil).StatePOST), req)
}

// StateUNLOCK mocks base method.
func (m *MockHttpServerCallback) StateUNLOCK(req *http.Request) {
	m.ctrl.T.Helper()
	m.ctrl.Call(m, "StateUNLOCK", req)
}

// StateUNLOCK indicates an expected call of StateUNLOCK.
func (mr *MockHttpServerCallbackMockRecorder) StateUNLOCK(req interface{}) *gomock.Call {
	mr.mock.ctrl.T.Helper()
	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateUNLOCK", reflect.TypeOf((*MockHttpServerCallback)(nil).StateUNLOCK), req)
}
