// Code generated by mockery v0.0.0-dev. DO NOT EDIT.

package mocks

import (
	context "context"

	mock "github.com/stretchr/testify/mock"

	testing "testing"
)

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

// Close provides a mock function with given fields:
func (_m *Client) 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
}

// Create provides a mock function with given fields: ctx, project, name
func (_m *Client) Create(ctx context.Context, project string, name string) error {
	ret := _m.Called(ctx, project, name)

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
		r0 = rf(ctx, project, name)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// Get provides a mock function with given fields: ctx, project, _a2, version
func (_m *Client) Get(ctx context.Context, project string, _a2 string, version string) (string, error) {
	ret := _m.Called(ctx, project, _a2, version)

	var r0 string
	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) string); ok {
		r0 = rf(ctx, project, _a2, version)
	} else {
		r0 = ret.Get(0).(string)
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok {
		r1 = rf(ctx, project, _a2, version)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// GrantAccess provides a mock function with given fields: ctx, project, name, serviceAccount
func (_m *Client) GrantAccess(ctx context.Context, project string, name string, serviceAccount string) error {
	ret := _m.Called(ctx, project, name, serviceAccount)

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok {
		r0 = rf(ctx, project, name, serviceAccount)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// RevokeAccess provides a mock function with given fields: ctx, project, name, serviceAccount
func (_m *Client) RevokeAccess(ctx context.Context, project string, name string, serviceAccount string) error {
	ret := _m.Called(ctx, project, name, serviceAccount)

	var r0 error
	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) error); ok {
		r0 = rf(ctx, project, name, serviceAccount)
	} else {
		r0 = ret.Error(0)
	}

	return r0
}

// Update provides a mock function with given fields: ctx, project, name, value
func (_m *Client) Update(ctx context.Context, project string, name string, value string) (string, error) {
	ret := _m.Called(ctx, project, name, value)

	var r0 string
	if rf, ok := ret.Get(0).(func(context.Context, string, string, string) string); ok {
		r0 = rf(ctx, project, name, value)
	} else {
		r0 = ret.Get(0).(string)
	}

	var r1 error
	if rf, ok := ret.Get(1).(func(context.Context, string, string, string) error); ok {
		r1 = rf(ctx, project, name, value)
	} else {
		r1 = ret.Error(1)
	}

	return r0, r1
}

// NewClient creates a new instance of Client. It also registers a cleanup function to assert the mocks expectations.
func NewClient(t testing.TB) *Client {
	mock := &Client{}

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

	return mock
}
