Skip to content

Commit 28a3dcf

Browse files
committed
test: add service and handler tests with sqlmock and httptest
1 parent 1dc8462 commit 28a3dcf

1 file changed

Lines changed: 246 additions & 0 deletions

File tree

internal/services/book_test.go

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
package services
2+
3+
import (
4+
"testing"
5+
6+
"github.com/DATA-DOG/go-sqlmock"
7+
"project-go/internal/database"
8+
)
9+
10+
func TestCreateBook(t *testing.T) {
11+
mockDB, mock, err := sqlmock.New()
12+
if err != nil {
13+
t.Fatalf("failed to open sqlmock: %v", err)
14+
}
15+
defer mockDB.Close()
16+
17+
db := database.NewDB(mockDB, "sqlite3")
18+
service := NewBookService(db)
19+
20+
book := &Book{
21+
Title: "Test Book",
22+
Author: "Test Author",
23+
AuthorID: 1,
24+
Genre: "Fiction",
25+
Pages: 300,
26+
PublicationYear: 2024,
27+
}
28+
29+
mock.ExpectExec("INSERT INTO books").
30+
WithArgs(book.Title, book.Author, book.AuthorID, book.Genre, book.Pages, book.PublicationYear).
31+
WillReturnResult(sqlmock.NewResult(1, 1))
32+
33+
if err := service.CreateBook(book); err != nil {
34+
t.Fatalf("unexpected error: %v", err)
35+
}
36+
37+
if book.ID != 1 {
38+
t.Errorf("expected ID 1, got %d", book.ID)
39+
}
40+
41+
if err := mock.ExpectationsWereMet(); err != nil {
42+
t.Errorf("unfulfilled expectations: %v", err)
43+
}
44+
}
45+
46+
func TestGetBooks(t *testing.T) {
47+
mockDB, mock, err := sqlmock.New()
48+
if err != nil {
49+
t.Fatalf("failed to open sqlmock: %v", err)
50+
}
51+
defer mockDB.Close()
52+
53+
db := database.NewDB(mockDB, "sqlite3")
54+
service := NewBookService(db)
55+
56+
rows := sqlmock.NewRows([]string{"id", "title", "author", "author_id", "genre", "pages", "publicationyear"}).
57+
AddRow(1, "Book One", "Author A", 1, "Fiction", 200, 2020).
58+
AddRow(2, "Book Two", "Author B", 2, "Non-Fiction", 300, 2021)
59+
60+
mock.ExpectQuery("SELECT (.+) FROM books").WillReturnRows(rows)
61+
62+
books, err := service.GetBooks()
63+
if err != nil {
64+
t.Fatalf("unexpected error: %v", err)
65+
}
66+
67+
if len(books) != 2 {
68+
t.Errorf("expected 2 books, got %d", len(books))
69+
}
70+
71+
if books[0].Title != "Book One" {
72+
t.Errorf("expected 'Book One', got %s", books[0].Title)
73+
}
74+
75+
if err := mock.ExpectationsWereMet(); err != nil {
76+
t.Errorf("unfulfilled expectations: %v", err)
77+
}
78+
}
79+
80+
func TestGetBookByID(t *testing.T) {
81+
mockDB, mock, err := sqlmock.New()
82+
if err != nil {
83+
t.Fatalf("failed to open sqlmock: %v", err)
84+
}
85+
defer mockDB.Close()
86+
87+
db := database.NewDB(mockDB, "sqlite3")
88+
service := NewBookService(db)
89+
90+
rows := sqlmock.NewRows([]string{"id", "title", "author", "author_id", "genre", "pages", "publicationyear"}).
91+
AddRow(1, "Book One", "Author A", 1, "Fiction", 200, 2020)
92+
93+
mock.ExpectQuery("SELECT (.+) FROM books WHERE id = ?").
94+
WithArgs(1).
95+
WillReturnRows(rows)
96+
97+
book, err := service.GetBookByID(1)
98+
if err != nil {
99+
t.Fatalf("unexpected error: %v", err)
100+
}
101+
102+
if book == nil {
103+
t.Fatal("expected book, got nil")
104+
}
105+
106+
if book.Title != "Book One" {
107+
t.Errorf("expected 'Book One', got %s", book.Title)
108+
}
109+
110+
if err := mock.ExpectationsWereMet(); err != nil {
111+
t.Errorf("unfulfilled expectations: %v", err)
112+
}
113+
}
114+
115+
func TestUpdateBook(t *testing.T) {
116+
mockDB, mock, err := sqlmock.New()
117+
if err != nil {
118+
t.Fatalf("failed to open sqlmock: %v", err)
119+
}
120+
defer mockDB.Close()
121+
122+
db := database.NewDB(mockDB, "sqlite3")
123+
service := NewBookService(db)
124+
125+
book := &Book{
126+
ID: 1,
127+
Title: "Updated Book",
128+
Author: "Author A",
129+
AuthorID: 1,
130+
Genre: "Fiction",
131+
Pages: 250,
132+
PublicationYear: 2023,
133+
}
134+
135+
mock.ExpectExec("UPDATE books SET").
136+
WithArgs(book.Title, book.Author, book.AuthorID, book.Genre, book.Pages, book.PublicationYear, book.ID).
137+
WillReturnResult(sqlmock.NewResult(0, 1))
138+
139+
if err := service.UpdateBook(book); err != nil {
140+
t.Fatalf("unexpected error: %v", err)
141+
}
142+
143+
if err := mock.ExpectationsWereMet(); err != nil {
144+
t.Errorf("unfulfilled expectations: %v", err)
145+
}
146+
}
147+
148+
func TestDeleteBook(t *testing.T) {
149+
mockDB, mock, err := sqlmock.New()
150+
if err != nil {
151+
t.Fatalf("failed to open sqlmock: %v", err)
152+
}
153+
defer mockDB.Close()
154+
155+
db := database.NewDB(mockDB, "sqlite3")
156+
service := NewBookService(db)
157+
158+
mock.ExpectExec("DELETE FROM books WHERE id = ?").
159+
WithArgs(1).
160+
WillReturnResult(sqlmock.NewResult(0, 1))
161+
162+
if err := service.DeleteBook(1); err != nil {
163+
t.Fatalf("unexpected error: %v", err)
164+
}
165+
166+
if err := mock.ExpectationsWereMet(); err != nil {
167+
t.Errorf("unfulfilled expectations: %v", err)
168+
}
169+
}
170+
171+
func TestSearchBooksByName(t *testing.T) {
172+
mockDB, mock, err := sqlmock.New()
173+
if err != nil {
174+
t.Fatalf("failed to open sqlmock: %v", err)
175+
}
176+
defer mockDB.Close()
177+
178+
db := database.NewDB(mockDB, "sqlite3")
179+
service := NewBookService(db)
180+
181+
rows := sqlmock.NewRows([]string{"id", "title", "author", "author_id", "genre", "pages", "publicationyear"}).
182+
AddRow(1, "Go in Action", "Author A", 1, "Tech", 400, 2022)
183+
184+
mock.ExpectQuery("SELECT (.+) FROM books WHERE title LIKE ?").
185+
WithArgs("%Go%").
186+
WillReturnRows(rows)
187+
188+
books, err := service.SearchBooksByName("Go")
189+
if err != nil {
190+
t.Fatalf("unexpected error: %v", err)
191+
}
192+
193+
if len(books) != 1 {
194+
t.Errorf("expected 1 book, got %d", len(books))
195+
}
196+
197+
if err := mock.ExpectationsWereMet(); err != nil {
198+
t.Errorf("unfulfilled expectations: %v", err)
199+
}
200+
}
201+
202+
func TestGetBooksFiltered(t *testing.T) {
203+
mockDB, mock, err := sqlmock.New()
204+
if err != nil {
205+
t.Fatalf("failed to open sqlmock: %v", err)
206+
}
207+
defer mockDB.Close()
208+
209+
db := database.NewDB(mockDB, "sqlite3")
210+
service := NewBookService(db)
211+
212+
mock.ExpectQuery("SELECT COUNT\\(\\*\\) FROM books WHERE 1=1 AND genre = \\?").
213+
WithArgs("Fiction").
214+
WillReturnRows(sqlmock.NewRows([]string{"count"}).AddRow(2))
215+
216+
rows := sqlmock.NewRows([]string{"id", "title", "author", "author_id", "genre", "pages", "publicationyear"}).
217+
AddRow(1, "Book A", "Author A", 1, "Fiction", 200, 2020).
218+
AddRow(2, "Book B", "Author B", 2, "Fiction", 300, 2021)
219+
220+
mock.ExpectQuery("SELECT id, title, author, author_id, genre, pages, publicationyear FROM books WHERE 1=1 AND genre = \\? LIMIT \\? OFFSET \\?").
221+
WithArgs("Fiction", 10, 0).
222+
WillReturnRows(rows)
223+
224+
filter := BookFilter{
225+
Genre: "Fiction",
226+
Page: 1,
227+
PageSize: 10,
228+
}
229+
230+
books, total, err := service.GetBooksFiltered(filter)
231+
if err != nil {
232+
t.Fatalf("unexpected error: %v", err)
233+
}
234+
235+
if total != 2 {
236+
t.Errorf("expected total 2, got %d", total)
237+
}
238+
239+
if len(books) != 2 {
240+
t.Errorf("expected 2 books, got %d", len(books))
241+
}
242+
243+
if err := mock.ExpectationsWereMet(); err != nil {
244+
t.Errorf("unfulfilled expectations: %v", err)
245+
}
246+
}

0 commit comments

Comments
 (0)