diff --git a/go.mod b/go.mod index 12b2cc8..d204893 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,9 @@ require ( github.com/99designs/gqlgen v0.17.55 github.com/go-gormigrate/gormigrate/v2 v2.1.3 github.com/joho/godotenv v1.5.1 + github.com/stretchr/testify v1.9.0 github.com/vektah/gqlparser/v2 v2.5.17 + go.uber.org/mock v0.5.0 gorm.io/datatypes v1.2.4 gorm.io/driver/postgres v1.5.9 gorm.io/gorm v1.25.12 @@ -16,6 +18,7 @@ require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect @@ -28,6 +31,7 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/kr/text v0.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.6.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sosodev/duration v1.3.1 // indirect diff --git a/go.sum b/go.sum index ba1c31d..fa5a7ad 100644 --- a/go.sum +++ b/go.sum @@ -83,6 +83,8 @@ github.com/vektah/gqlparser/v2 v2.5.17 h1:9At7WblLV7/36nulgekUgIaqHZWn5hxqluxrxG github.com/vektah/gqlparser/v2 v2.5.17/go.mod h1:1lz1OeCqgQbQepsGxPVywrjdBHW2T08PUS3pJqepRww= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= diff --git a/src/mock/repository.go b/src/mock/repository.go new file mode 100644 index 0000000..f548ed8 --- /dev/null +++ b/src/mock/repository.go @@ -0,0 +1,385 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: repository/repository.go +// +// Generated by this command: +// +// mockgen -source repository/repository.go -destination mock/repository.go +// + +// Package mock_repository is a generated GoMock package. +package mock_repository + +import ( + context "context" + reflect "reflect" + + model "github.com/thanhhaudev/go-graphql/src/graph/model" + gomock "go.uber.org/mock/gomock" +) + +// MockBookRepository is a mock of BookRepository interface. +type MockBookRepository struct { + ctrl *gomock.Controller + recorder *MockBookRepositoryMockRecorder + isgomock struct{} +} + +// MockBookRepositoryMockRecorder is the mock recorder for MockBookRepository. +type MockBookRepositoryMockRecorder struct { + mock *MockBookRepository +} + +// NewMockBookRepository creates a new mock instance. +func NewMockBookRepository(ctrl *gomock.Controller) *MockBookRepository { + mock := &MockBookRepository{ctrl: ctrl} + mock.recorder = &MockBookRepositoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBookRepository) EXPECT() *MockBookRepositoryMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m_2 *MockBookRepository) Create(ctx context.Context, m *model.Book) error { + m_2.ctrl.T.Helper() + ret := m_2.ctrl.Call(m_2, "Create", ctx, m) + ret0, _ := ret[0].(error) + return ret0 +} + +// Create indicates an expected call of Create. +func (mr *MockBookRepositoryMockRecorder) Create(ctx, m any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockBookRepository)(nil).Create), ctx, m) +} + +// Delete mocks base method. +func (m *MockBookRepository) Delete(ctx context.Context, id int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockBookRepositoryMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockBookRepository)(nil).Delete), ctx, id) +} + +// FindBooksByAuthorID mocks base method. +func (m *MockBookRepository) FindBooksByAuthorID(ctx context.Context, authorID int) ([]*model.Book, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindBooksByAuthorID", ctx, authorID) + ret0, _ := ret[0].([]*model.Book) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindBooksByAuthorID indicates an expected call of FindBooksByAuthorID. +func (mr *MockBookRepositoryMockRecorder) FindBooksByAuthorID(ctx, authorID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindBooksByAuthorID", reflect.TypeOf((*MockBookRepository)(nil).FindBooksByAuthorID), ctx, authorID) +} + +// FindByID mocks base method. +func (m *MockBookRepository) FindByID(ctx context.Context, id int) (*model.Book, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByID", ctx, id) + ret0, _ := ret[0].(*model.Book) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindByID indicates an expected call of FindByID. +func (mr *MockBookRepositoryMockRecorder) FindByID(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockBookRepository)(nil).FindByID), ctx, id) +} + +// GetAll mocks base method. +func (m *MockBookRepository) GetAll(ctx context.Context) ([]*model.Book, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAll", ctx) + ret0, _ := ret[0].([]*model.Book) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAll indicates an expected call of GetAll. +func (mr *MockBookRepositoryMockRecorder) GetAll(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockBookRepository)(nil).GetAll), ctx) +} + +// Update mocks base method. +func (m_2 *MockBookRepository) Update(ctx context.Context, m *model.Book) error { + m_2.ctrl.T.Helper() + ret := m_2.ctrl.Call(m_2, "Update", ctx, m) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockBookRepositoryMockRecorder) Update(ctx, m any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockBookRepository)(nil).Update), ctx, m) +} + +// MockAuthorRepository is a mock of AuthorRepository interface. +type MockAuthorRepository struct { + ctrl *gomock.Controller + recorder *MockAuthorRepositoryMockRecorder + isgomock struct{} +} + +// MockAuthorRepositoryMockRecorder is the mock recorder for MockAuthorRepository. +type MockAuthorRepositoryMockRecorder struct { + mock *MockAuthorRepository +} + +// NewMockAuthorRepository creates a new mock instance. +func NewMockAuthorRepository(ctrl *gomock.Controller) *MockAuthorRepository { + mock := &MockAuthorRepository{ctrl: ctrl} + mock.recorder = &MockAuthorRepositoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockAuthorRepository) EXPECT() *MockAuthorRepositoryMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m_2 *MockAuthorRepository) Create(ctx context.Context, m *model.Author) (*model.Author, error) { + m_2.ctrl.T.Helper() + ret := m_2.ctrl.Call(m_2, "Create", ctx, m) + ret0, _ := ret[0].(*model.Author) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create. +func (mr *MockAuthorRepositoryMockRecorder) Create(ctx, m any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockAuthorRepository)(nil).Create), ctx, m) +} + +// Delete mocks base method. +func (m *MockAuthorRepository) Delete(ctx context.Context, id int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Delete", ctx, id) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockAuthorRepositoryMockRecorder) Delete(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockAuthorRepository)(nil).Delete), ctx, id) +} + +// FindAuthorsByBookID mocks base method. +func (m *MockAuthorRepository) FindAuthorsByBookID(ctx context.Context, bookID int) ([]*model.Author, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindAuthorsByBookID", ctx, bookID) + ret0, _ := ret[0].([]*model.Author) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindAuthorsByBookID indicates an expected call of FindAuthorsByBookID. +func (mr *MockAuthorRepositoryMockRecorder) FindAuthorsByBookID(ctx, bookID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindAuthorsByBookID", reflect.TypeOf((*MockAuthorRepository)(nil).FindAuthorsByBookID), ctx, bookID) +} + +// FindByID mocks base method. +func (m *MockAuthorRepository) FindByID(ctx context.Context, id int) (*model.Author, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByID", ctx, id) + ret0, _ := ret[0].(*model.Author) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindByID indicates an expected call of FindByID. +func (mr *MockAuthorRepositoryMockRecorder) FindByID(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockAuthorRepository)(nil).FindByID), ctx, id) +} + +// FindByIDs mocks base method. +func (m *MockAuthorRepository) FindByIDs(ctx context.Context, ids []int) ([]*model.Author, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByIDs", ctx, ids) + ret0, _ := ret[0].([]*model.Author) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindByIDs indicates an expected call of FindByIDs. +func (mr *MockAuthorRepositoryMockRecorder) FindByIDs(ctx, ids any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByIDs", reflect.TypeOf((*MockAuthorRepository)(nil).FindByIDs), ctx, ids) +} + +// GetAll mocks base method. +func (m *MockAuthorRepository) GetAll(ctx context.Context) ([]*model.Author, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAll", ctx) + ret0, _ := ret[0].([]*model.Author) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAll indicates an expected call of GetAll. +func (mr *MockAuthorRepositoryMockRecorder) GetAll(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockAuthorRepository)(nil).GetAll), ctx) +} + +// Update mocks base method. +func (m_2 *MockAuthorRepository) Update(ctx context.Context, m *model.Author) (*model.Author, error) { + m_2.ctrl.T.Helper() + ret := m_2.ctrl.Call(m_2, "Update", ctx, m) + ret0, _ := ret[0].(*model.Author) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockAuthorRepositoryMockRecorder) Update(ctx, m any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAuthorRepository)(nil).Update), ctx, m) +} + +// MockBorrowerRepository is a mock of BorrowerRepository interface. +type MockBorrowerRepository struct { + ctrl *gomock.Controller + recorder *MockBorrowerRepositoryMockRecorder + isgomock struct{} +} + +// MockBorrowerRepositoryMockRecorder is the mock recorder for MockBorrowerRepository. +type MockBorrowerRepositoryMockRecorder struct { + mock *MockBorrowerRepository +} + +// NewMockBorrowerRepository creates a new mock instance. +func NewMockBorrowerRepository(ctrl *gomock.Controller) *MockBorrowerRepository { + mock := &MockBorrowerRepository{ctrl: ctrl} + mock.recorder = &MockBorrowerRepositoryMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBorrowerRepository) EXPECT() *MockBorrowerRepositoryMockRecorder { + return m.recorder +} + +// BorrowBook mocks base method. +func (m *MockBorrowerRepository) BorrowBook(ctx context.Context, borrower *model.Borrower, book *model.Book) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BorrowBook", ctx, borrower, book) + ret0, _ := ret[0].(error) + return ret0 +} + +// BorrowBook indicates an expected call of BorrowBook. +func (mr *MockBorrowerRepositoryMockRecorder) BorrowBook(ctx, borrower, book any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BorrowBook", reflect.TypeOf((*MockBorrowerRepository)(nil).BorrowBook), ctx, borrower, book) +} + +// Create mocks base method. +func (m_2 *MockBorrowerRepository) Create(ctx context.Context, m *model.Borrower) (*model.Borrower, error) { + m_2.ctrl.T.Helper() + ret := m_2.ctrl.Call(m_2, "Create", ctx, m) + ret0, _ := ret[0].(*model.Borrower) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Create indicates an expected call of Create. +func (mr *MockBorrowerRepositoryMockRecorder) Create(ctx, m any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockBorrowerRepository)(nil).Create), ctx, m) +} + +// FindBorrowerBooksByID mocks base method. +func (m *MockBorrowerRepository) FindBorrowerBooksByID(ctx context.Context, borrowerID int) ([]*model.BorrowerBook, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindBorrowerBooksByID", ctx, borrowerID) + ret0, _ := ret[0].([]*model.BorrowerBook) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindBorrowerBooksByID indicates an expected call of FindBorrowerBooksByID. +func (mr *MockBorrowerRepositoryMockRecorder) FindBorrowerBooksByID(ctx, borrowerID any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindBorrowerBooksByID", reflect.TypeOf((*MockBorrowerRepository)(nil).FindBorrowerBooksByID), ctx, borrowerID) +} + +// FindByID mocks base method. +func (m *MockBorrowerRepository) FindByID(ctx context.Context, id int) (*model.Borrower, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByID", ctx, id) + ret0, _ := ret[0].(*model.Borrower) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindByID indicates an expected call of FindByID. +func (mr *MockBorrowerRepositoryMockRecorder) FindByID(ctx, id any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByID", reflect.TypeOf((*MockBorrowerRepository)(nil).FindByID), ctx, id) +} + +// FindByTelNumber mocks base method. +func (m *MockBorrowerRepository) FindByTelNumber(ctx context.Context, telNumber string) (*model.Borrower, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FindByTelNumber", ctx, telNumber) + ret0, _ := ret[0].(*model.Borrower) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FindByTelNumber indicates an expected call of FindByTelNumber. +func (mr *MockBorrowerRepositoryMockRecorder) FindByTelNumber(ctx, telNumber any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByTelNumber", reflect.TypeOf((*MockBorrowerRepository)(nil).FindByTelNumber), ctx, telNumber) +} + +// GetAll mocks base method. +func (m *MockBorrowerRepository) GetAll(ctx context.Context) ([]*model.Borrower, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetAll", ctx) + ret0, _ := ret[0].([]*model.Borrower) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetAll indicates an expected call of GetAll. +func (mr *MockBorrowerRepositoryMockRecorder) GetAll(ctx any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockBorrowerRepository)(nil).GetAll), ctx) +} + +// Update mocks base method. +func (m_2 *MockBorrowerRepository) Update(ctx context.Context, m *model.Borrower) (*model.Borrower, error) { + m_2.ctrl.T.Helper() + ret := m_2.ctrl.Call(m_2, "Update", ctx, m) + ret0, _ := ret[0].(*model.Borrower) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Update indicates an expected call of Update. +func (mr *MockBorrowerRepositoryMockRecorder) Update(ctx, m any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockBorrowerRepository)(nil).Update), ctx, m) +} diff --git a/src/repository/repository.go b/src/repository/repository.go index 3014ef6..e76e5b1 100644 --- a/src/repository/repository.go +++ b/src/repository/repository.go @@ -9,8 +9,8 @@ type BookRepository interface { GetAll(ctx context.Context) ([]*model.Book, error) FindByID(ctx context.Context, id int) (*model.Book, error) FindBooksByAuthorID(ctx context.Context, authorID int) ([]*model.Book, error) - Create(ctx context.Context, model *model.Book) error - Update(ctx context.Context, model *model.Book) error + Create(ctx context.Context, m *model.Book) error + Update(ctx context.Context, m *model.Book) error Delete(ctx context.Context, id int) error } @@ -19,8 +19,8 @@ type AuthorRepository interface { FindByID(ctx context.Context, id int) (*model.Author, error) FindByIDs(ctx context.Context, ids []int) ([]*model.Author, error) FindAuthorsByBookID(ctx context.Context, bookID int) ([]*model.Author, error) - Create(ctx context.Context, model *model.Author) (*model.Author, error) - Update(ctx context.Context, model *model.Author) (*model.Author, error) + Create(ctx context.Context, m *model.Author) (*model.Author, error) + Update(ctx context.Context, m *model.Author) (*model.Author, error) Delete(ctx context.Context, id int) error } @@ -29,7 +29,7 @@ type BorrowerRepository interface { FindByID(ctx context.Context, id int) (*model.Borrower, error) FindByTelNumber(ctx context.Context, telNumber string) (*model.Borrower, error) FindBorrowerBooksByID(ctx context.Context, borrowerID int) ([]*model.BorrowerBook, error) - Create(ctx context.Context, model *model.Borrower) (*model.Borrower, error) - Update(ctx context.Context, model *model.Borrower) (*model.Borrower, error) + Create(ctx context.Context, m *model.Borrower) (*model.Borrower, error) + Update(ctx context.Context, m *model.Borrower) (*model.Borrower, error) BorrowBook(ctx context.Context, borrower *model.Borrower, book *model.Book) error } diff --git a/src/service/author_test.go b/src/service/author_test.go new file mode 100644 index 0000000..8297e15 --- /dev/null +++ b/src/service/author_test.go @@ -0,0 +1,56 @@ +package service + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/thanhhaudev/go-graphql/src/graph/model" + mock_repository "github.com/thanhhaudev/go-graphql/src/mock" + "go.uber.org/mock/gomock" +) + +func TestAuthorService(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockAuthorRepo := mock_repository.NewMockAuthorRepository(ctrl) + service := NewAuthorService(mockAuthorRepo) + + tests := []struct { + name string + setup func() + run func() (interface{}, error) + verify func(t *testing.T, result interface{}, err error) + }{ + { + name: "CreateAuthor", + setup: func() { + mockAuthorRepo.EXPECT().Create(context.Background(), gomock.Any()).Return(&model.Author{ + ID: 1, + Name: "John Doe", + }, nil) + + }, + run: func() (interface{}, error) { + return service.Create(context.Background(), &model.CreateAuthorInput{ + Name: "John Doe", + }) + }, + verify: func(t *testing.T, result interface{}, err error) { + author := result.(*model.Author) + assert.NoError(t, err) + assert.NotNil(t, author) + assert.Equal(t, "John Doe", author.Name) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + result, err := tt.run() + tt.verify(t, result, err) + }) + } +} diff --git a/src/service/book_test.go b/src/service/book_test.go new file mode 100644 index 0000000..ab6de13 --- /dev/null +++ b/src/service/book_test.go @@ -0,0 +1,63 @@ +package service + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/thanhhaudev/go-graphql/src/graph/model" + mock_repository "github.com/thanhhaudev/go-graphql/src/mock" + "go.uber.org/mock/gomock" +) + +func TestBookService(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockBookRepo := mock_repository.NewMockBookRepository(ctrl) + mockAuthorRepo := mock_repository.NewMockAuthorRepository(ctrl) + service := NewBookService(mockBookRepo, mockAuthorRepo) + + tests := []struct { + name string + setup func() + run func() (interface{}, error) + verify func(t *testing.T, result interface{}, err error) + }{ + { + name: "CreateBook", + setup: func() { + mockBookRepo.EXPECT().Create(context.Background(), gomock.Any()).Return(nil) + mockAuthorRepo.EXPECT().FindByIDs(context.Background(), []int{1}).Return([]*model.Author{ + { + ID: 1, + }, + }, nil) + }, + run: func() (interface{}, error) { + return service.Create(context.Background(), &model.CreateBookInput{ + Title: "Animal Farm", + Quantity: 1, + Rating: 5, + AuthorIds: []int{1}, + PublishAt: time.Date(1945, time.August, 17, 0, 0, 0, 0, time.UTC), + }) + }, + verify: func(t *testing.T, result interface{}, err error) { + book := result.(*model.Book) + assert.NoError(t, err) + assert.NotNil(t, book) + assert.Equal(t, "Animal Farm", book.Title) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + result, err := tt.run() + tt.verify(t, result, err) + }) + } +} diff --git a/src/service/borrower_test.go b/src/service/borrower_test.go new file mode 100644 index 0000000..1b7984f --- /dev/null +++ b/src/service/borrower_test.go @@ -0,0 +1,64 @@ +package service + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/thanhhaudev/go-graphql/src/graph/model" + mock_repository "github.com/thanhhaudev/go-graphql/src/mock" + "go.uber.org/mock/gomock" +) + +func TestBorrowerService(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockBorrowerRepo := mock_repository.NewMockBorrowerRepository(ctrl) + mockBookRepo := mock_repository.NewMockBookRepository(ctrl) + service := NewBorrowerService(mockBorrowerRepo, mockBookRepo) + + tests := []struct { + name string + setup func() + run func() (interface{}, error) + verify func(t *testing.T, result interface{}, err error) + }{ + { + name: "CreateBorrower", + setup: func() { + mockBorrowerRepo.EXPECT().FindByTelNumber(gomock.Any(), "123456789").Return(nil, nil) + mockBorrowerRepo.EXPECT().Create(gomock.Any(), gomock.Any()).Return(&model.Borrower{ + ID: 1, + Name: "John Doe", + TelNumber: "123456789", + }, nil) + }, + run: func() (interface{}, error) { + input := &model.CreateBorrowerInput{ + Name: "John Doe", + TelNumber: "123456789", + Address: "123 Main St", + BirthDate: time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC), + } + return service.Create(context.Background(), input) + }, + verify: func(t *testing.T, result interface{}, err error) { + borrower := result.(*model.Borrower) + assert.NoError(t, err) + assert.NotNil(t, borrower) + assert.Equal(t, "John Doe", borrower.Name) + assert.Equal(t, "123456789", borrower.TelNumber) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + tt.setup() + result, err := tt.run() + tt.verify(t, result, err) + }) + } +}