chore: release [ci skip]

This commit is contained in:
gitea-actions
2026-04-01 08:29:21 +00:00
parent 5a7b70145c
commit dd3c09865f
12 changed files with 451 additions and 342 deletions
@@ -31,7 +31,9 @@ public class CustomerEntityTest {
// 3. Truy vấn lại để kiểm tra (Sửa lại class map của query thành CustomerEntity) // 3. Truy vấn lại để kiểm tra (Sửa lại class map của query thành CustomerEntity)
var query = entityManager.createQuery( var query = entityManager.createQuery(
"SELECT c FROM CustomerEntity c WHERE c.phone = :phone", CustomerEntity.class); "SELECT c FROM CustomerEntity c WHERE c.phone = :phone",
CustomerEntity.class
);
query.setParameter("phone", "+84987654321"); query.setParameter("phone", "+84987654321");
// Nhận kết quả về đúng kiểu CustomerEntity // Nhận kết quả về đúng kiểu CustomerEntity
@@ -39,8 +41,16 @@ public class CustomerEntityTest {
// 4. Assert (Kiểm chứng) // 4. Assert (Kiểm chứng)
Assertions.assertNotNull(savedCustomer, "Customer không được null"); Assertions.assertNotNull(savedCustomer, "Customer không được null");
Assertions.assertEquals("Nguyen Van A", savedCustomer.name, "Tên không khớp"); Assertions.assertEquals(
Assertions.assertEquals("+84987654321", savedCustomer.phone, "Số điện thoại không khớp"); "Nguyen Van A",
savedCustomer.name,
"Tên không khớp"
);
Assertions.assertEquals(
"+84987654321",
savedCustomer.phone,
"Số điện thoại không khớp"
);
Assertions.assertNotNull(savedCustomer.id, "ID chưa được sinh ra"); Assertions.assertNotNull(savedCustomer.id, "ID chưa được sinh ra");
} }
} }
@@ -37,7 +37,10 @@ public class UserModelTest {
assertEquals(phone, user.phone); assertEquals(phone, user.phone);
assertNotNull(user.hashedPassword, "Password phải được hash"); assertNotNull(user.hashedPassword, "Password phải được hash");
TestUserEntity savedUser = TestUserEntity.find("phone", phone).firstResult(); TestUserEntity savedUser = TestUserEntity.find(
"phone",
phone
).firstResult();
assertNotNull(savedUser, "Phải tìm thấy user trong database"); assertNotNull(savedUser, "Phải tìm thấy user trong database");
} }
@@ -53,7 +56,10 @@ public class UserModelTest {
assertNotNull(user.id, "ID not null after persist"); assertNotNull(user.id, "ID not null after persist");
assertEquals(phone, user.name, "Tên mặc định phải là số điện thoại"); assertEquals(phone, user.name, "Tên mặc định phải là số điện thoại");
assertEquals(phone, user.phone); assertEquals(phone, user.phone);
assertNotNull(user.hashedPassword, "Password tự động phải được tạo và hash"); assertNotNull(
user.hashedPassword,
"Password tự động phải được tạo và hash"
);
} }
// 3. Test case: Đăng ký thất bại do số điện thoại đã tồn tại // 3. Test case: Đăng ký thất bại do số điện thoại đã tồn tại
@@ -69,9 +75,12 @@ public class UserModelTest {
// Tạo user thứ hai với cùng số điện thoại // Tạo user thứ hai với cùng số điện thoại
TestUserEntity newUser = new TestUserEntity(); TestUserEntity newUser = new TestUserEntity();
BadRequestException exception = assertThrows(BadRequestException.class, () -> { BadRequestException exception = assertThrows(
BadRequestException.class,
() -> {
newUser.signup("Nguyen Viet Anh", phone, "02092006Anh"); newUser.signup("Nguyen Viet Anh", phone, "02092006Anh");
}); }
);
assertEquals("ExistedUser", exception.getMessage()); assertEquals("ExistedUser", exception.getMessage());
} }
@@ -83,9 +92,12 @@ public class UserModelTest {
TestUserEntity user = new TestUserEntity(); TestUserEntity user = new TestUserEntity();
String invalidPhone = "12345"; String invalidPhone = "12345";
BadRequestException exception = assertThrows(BadRequestException.class, () -> { BadRequestException exception = assertThrows(
BadRequestException.class,
() -> {
user.signup("Lam Vi Hoang", invalidPhone, "Pass123"); user.signup("Lam Vi Hoang", invalidPhone, "Pass123");
}); }
);
assertEquals("InvalidPhoneNumber", exception.getMessage()); assertEquals("InvalidPhoneNumber", exception.getMessage());
} }
@@ -130,7 +142,9 @@ public class UserModelTest {
boolean loginResult = user.login("anhdomixi"); boolean loginResult = user.login("anhdomixi");
assertFalse(loginResult, "Đăng nhập phải thất bại nếu hashedPassword là null"); assertFalse(
loginResult,
"Đăng nhập phải thất bại nếu hashedPassword là null"
);
} }
} }
@@ -20,7 +20,6 @@ public class AuthenticationServiceTest {
return "+8477" + String.format("%07d", random.nextInt(10000000)); return "+8477" + String.format("%07d", random.nextInt(10000000));
} }
@Test @Test
void testSignup() { void testSignup() {
String phone = generateRandomPhone(); String phone = generateRandomPhone();
@@ -16,7 +16,8 @@ public class OtpServiceTest {
// 1. Test case: Tạo và lưu OTP thành công // 1. Test case: Tạo và lưu OTP thành công
@Test @Test
public void testGenerateAndSaveOtp() { public void testGenerateAndSaveOtp() {
String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); String phone =
"+8477" + String.format("%07d", new Random().nextInt(10000000));
String otp = otpService.generateAndSaveOtp(phone); String otp = otpService.generateAndSaveOtp(phone);
assertNotNull(otp, "OTP sinh ra không được null"); assertNotNull(otp, "OTP sinh ra không được null");
@@ -27,7 +28,8 @@ public class OtpServiceTest {
// 2. Test case: Xác thực OTP thành công // 2. Test case: Xác thực OTP thành công
@Test @Test
public void testVerifyOtpSuccess() { public void testVerifyOtpSuccess() {
String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); String phone =
"+8477" + String.format("%07d", new Random().nextInt(10000000));
String generatedOtp = otpService.generateAndSaveOtp(phone); String generatedOtp = otpService.generateAndSaveOtp(phone);
// Xác thực với OTP vừa tạo ra // Xác thực với OTP vừa tạo ra
@@ -39,7 +41,8 @@ public class OtpServiceTest {
// 3. Test case: Xác thực thất bại do sai mã OTP // 3. Test case: Xác thực thất bại do sai mã OTP
@Test @Test
public void testVerifyOtpFailWrongOtp() { public void testVerifyOtpFailWrongOtp() {
String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); String phone =
"+8477" + String.format("%07d", new Random().nextInt(10000000));
otpService.generateAndSaveOtp(phone); // Tạo OTP nhưng không dùng otpService.generateAndSaveOtp(phone); // Tạo OTP nhưng không dùng
String wrongOtp = "999999"; // Giả sử mã sai String wrongOtp = "999999"; // Giả sử mã sai
@@ -51,18 +54,23 @@ public class OtpServiceTest {
// 4. Test case: Xác thực thất bại do OTP không tồn tại (chưa tạo hoặc đã hết hạn) // 4. Test case: Xác thực thất bại do OTP không tồn tại (chưa tạo hoặc đã hết hạn)
@Test @Test
public void testVerifyOtpFailNotExists() { public void testVerifyOtpFailNotExists() {
String unverifiedPhone = "+8499" + String.format("%07d", new Random().nextInt(10000000)); String unverifiedPhone =
"+8499" + String.format("%07d", new Random().nextInt(10000000));
// Cố tình xác thực cho một số điện thoại chưa từng gọi generateAndSaveOtp // Cố tình xác thực cho một số điện thoại chưa từng gọi generateAndSaveOtp
boolean verifyResult = otpService.verifyOtp(unverifiedPhone, "123456"); boolean verifyResult = otpService.verifyOtp(unverifiedPhone, "123456");
assertFalse(verifyResult, "Xác thực phải thất bại với SĐT không có OTP trong Redis"); assertFalse(
verifyResult,
"Xác thực phải thất bại với SĐT không có OTP trong Redis"
);
} }
// 5. Test case: Đảm bảo OTP chỉ được sử dụng 1 lần (đã bị xóa sau khi verify thành công bằng lệnh getdel) // 5. Test case: Đảm bảo OTP chỉ được sử dụng 1 lần (đã bị xóa sau khi verify thành công bằng lệnh getdel)
@Test @Test
public void testVerifyOtpConsumedAfterSuccess() { public void testVerifyOtpConsumedAfterSuccess() {
String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); String phone =
"+8477" + String.format("%07d", new Random().nextInt(10000000));
String generatedOtp = otpService.generateAndSaveOtp(phone); String generatedOtp = otpService.generateAndSaveOtp(phone);
// Lần 1: Xác thực thành công // Lần 1: Xác thực thành công
@@ -70,6 +78,9 @@ public class OtpServiceTest {
// Lần 2: Xác thực lại cùng mã đó sẽ thất bại vì key đã bị getdel xóa khỏi Redis // Lần 2: Xác thực lại cùng mã đó sẽ thất bại vì key đã bị getdel xóa khỏi Redis
boolean secondVerifyResult = otpService.verifyOtp(phone, generatedOtp); boolean secondVerifyResult = otpService.verifyOtp(phone, generatedOtp);
assertFalse(secondVerifyResult, "OTP không được phép tái sử dụng sau khi đã verify thành công"); assertFalse(
secondVerifyResult,
"OTP không được phép tái sử dụng sau khi đã verify thành công"
);
} }
} }
@@ -8,25 +8,37 @@ public class PhoneValidatorTest {
@Test @Test
public void testValidVietnamesePhoneNumbers() { public void testValidVietnamesePhoneNumbers() {
// Số điện thoại VN hợp lệ (có mã vùng hoặc số 0 ở đầu đều được) // Số điện thoại VN hợp lệ (có mã vùng hoặc số 0 ở đầu đều được)
Assertions.assertTrue(PhoneValidator.isValidInternationalPhone("0987654321")); Assertions.assertTrue(
Assertions.assertTrue(PhoneValidator.isValidInternationalPhone("+84987654321")); PhoneValidator.isValidInternationalPhone("0987654321")
Assertions.assertTrue(PhoneValidator.isValidInternationalPhone("84987654321")); );
Assertions.assertTrue(
PhoneValidator.isValidInternationalPhone("+84987654321")
);
Assertions.assertTrue(
PhoneValidator.isValidInternationalPhone("84987654321")
);
} }
@Test @Test
public void testValidInternationalPhoneNumbers() { public void testValidInternationalPhoneNumbers() {
// Số điện thoại quốc tế hợp lệ (Ví dụ: Mỹ +1) // Số điện thoại quốc tế hợp lệ (Ví dụ: Mỹ +1)
Assertions.assertTrue(PhoneValidator.isValidInternationalPhone("+14155552671")); Assertions.assertTrue(
PhoneValidator.isValidInternationalPhone("+14155552671")
);
} }
@Test @Test
public void testInvalidPhoneNumbers() { public void testInvalidPhoneNumbers() {
// Chuỗi không phải số điện thoại // Chuỗi không phải số điện thoại
Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("not-a-phone-number")); Assertions.assertFalse(
PhoneValidator.isValidInternationalPhone("not-a-phone-number")
);
// Số điện thoại quá ngắn hoặc sai định dạng // Số điện thoại quá ngắn hoặc sai định dạng
Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("123")); Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("123"));
Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("099999999999999")); Assertions.assertFalse(
PhoneValidator.isValidInternationalPhone("099999999999999")
);
// Chuỗi rỗng // Chuỗi rỗng
Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("")); Assertions.assertFalse(PhoneValidator.isValidInternationalPhone(""));
@@ -23,7 +23,10 @@ public class InventoryItemEntityTest {
Assertions.assertNotNull(item, "Entity tạo ra không được null"); Assertions.assertNotNull(item, "Entity tạo ra không được null");
Assertions.assertEquals(name, item.name, "Tên không khớp"); Assertions.assertEquals(name, item.name, "Tên không khớp");
Assertions.assertEquals(unit, item.unit, "Đơn vị không khớp"); Assertions.assertEquals(unit, item.unit, "Đơn vị không khớp");
Assertions.assertNotNull(item.id, "ID phải được sinh ra tự động sau khi persist"); Assertions.assertNotNull(
item.id,
"ID phải được sinh ra tự động sau khi persist"
);
} }
@Test @Test
@@ -39,6 +42,9 @@ public class InventoryItemEntityTest {
Assertions.assertNotNull(item, "Entity tạo ra không được null"); Assertions.assertNotNull(item, "Entity tạo ra không được null");
Assertions.assertEquals(name, item.name, "Tên không khớp"); Assertions.assertEquals(name, item.name, "Tên không khớp");
Assertions.assertEquals("unit", item.unit, "Unit mặc định phải là 'unit'"); Assertions.assertEquals("unit", item.unit, "Unit mặc định phải là 'unit'");
Assertions.assertNotNull(item.id, "ID phải được sinh ra tự động sau khi persist"); Assertions.assertNotNull(
item.id,
"ID phải được sinh ra tự động sau khi persist"
);
} }
} }
@@ -24,7 +24,10 @@ public class MenuItemEntityTest {
assertEquals(name, menuItem.name, "Tên món ăn không khớp"); assertEquals(name, menuItem.name, "Tên món ăn không khớp");
assertEquals(price, menuItem.price, "Giá món ăn không khớp"); assertEquals(price, menuItem.price, "Giá món ăn không khớp");
assertNotNull(menuItem.id, "ID phải được tự động sinh ra sau khi persist"); assertNotNull(menuItem.id, "ID phải được tự động sinh ra sau khi persist");
assertTrue(menuItem.ingredients.isEmpty(), "Danh sách nguyên liệu ban đầu phải rỗng"); assertTrue(
menuItem.ingredients.isEmpty(),
"Danh sách nguyên liệu ban đầu phải rỗng"
);
} }
@Test @Test
@@ -32,10 +35,17 @@ public class MenuItemEntityTest {
public void testAddIngredientSuccessfully() { public void testAddIngredientSuccessfully() {
// 1. Chuẩn bị dữ liệu (Arrange) // 1. Chuẩn bị dữ liệu (Arrange)
// Tạo món ăn // Tạo món ăn
MenuItemEntity menuItem = MenuItemEntity.create("Trà sữa trân châu", 45000.0); MenuItemEntity menuItem = MenuItemEntity.create(
"Trà sữa trân châu",
45000.0
);
// Tạo nguyên liệu trong kho (Dùng đúng hàm add() của EateryInventoryItemEntity như đã fix) // Tạo nguyên liệu trong kho (Dùng đúng hàm add() của EateryInventoryItemEntity như đã fix)
EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create("Trân châu đen", 50, "kg"); EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create(
"Trân châu đen",
50,
"kg"
);
double requiredQty = 0.2; // Cần 0.2 kg trân châu cho 1 ly double requiredQty = 0.2; // Cần 0.2 kg trân châu cho 1 ly
@@ -44,15 +54,37 @@ public class MenuItemEntityTest {
// 3. Kiểm chứng (Assert) // 3. Kiểm chứng (Assert)
// Kiểm tra danh sách nguyên liệu của món ăn // Kiểm tra danh sách nguyên liệu của món ăn
assertFalse(menuItem.ingredients.isEmpty(), "Danh sách nguyên liệu không được rỗng sau khi thêm"); assertFalse(
assertEquals(1, menuItem.ingredients.size(), "Phải có đúng 1 nguyên liệu trong danh sách"); menuItem.ingredients.isEmpty(),
"Danh sách nguyên liệu không được rỗng sau khi thêm"
);
assertEquals(
1,
menuItem.ingredients.size(),
"Phải có đúng 1 nguyên liệu trong danh sách"
);
// Lấy phần tử nguyên liệu đầu tiên ra để kiểm tra chi tiết các liên kết // Lấy phần tử nguyên liệu đầu tiên ra để kiểm tra chi tiết các liên kết
MenuItemIngredientEntity addedIngredient = menuItem.ingredients.get(0); MenuItemIngredientEntity addedIngredient = menuItem.ingredients.get(0);
assertNotNull(addedIngredient.id, "ID của Entity trung gian phải được sinh ra"); assertNotNull(
assertEquals(menuItem.id, addedIngredient.menuItem.id, "Khóa ngoại MenuItem bị sai"); addedIngredient.id,
assertEquals(inventoryItem.id, addedIngredient.inventoryItem.id, "Khóa ngoại InventoryItem bị sai"); "ID của Entity trung gian phải được sinh ra"
assertEquals(requiredQty, addedIngredient.requiredQuantity, "Định lượng (requiredQty) không khớp"); );
assertEquals(
menuItem.id,
addedIngredient.menuItem.id,
"Khóa ngoại MenuItem bị sai"
);
assertEquals(
inventoryItem.id,
addedIngredient.inventoryItem.id,
"Khóa ngoại InventoryItem bị sai"
);
assertEquals(
requiredQty,
addedIngredient.requiredQuantity,
"Định lượng (requiredQty) không khớp"
);
} }
} }
@@ -27,7 +27,11 @@ public class MenuItemIngredientEntityTest {
String inventoryItemUnit = "l"; String inventoryItemUnit = "l";
// SỬA Ở ĐÂY: Khởi tạo bằng new và dùng hàm add() đúng như cấu trúc class của bạn // SỬA Ở ĐÂY: Khởi tạo bằng new và dùng hàm add() đúng như cấu trúc class của bạn
EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create(inventoryItemName, inventoryItemQuantity, inventoryItemUnit); EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create(
inventoryItemName,
inventoryItemQuantity,
inventoryItemUnit
);
// Lưu ý: Hàm add() của bạn đã có sẵn lệnh this.persist() bên trong nên không cần gọi lại nữa! // Lưu ý: Hàm add() của bạn đã có sẵn lệnh this.persist() bên trong nên không cần gọi lại nữa!
double requiredQuantity = 0.5; double requiredQuantity = 0.5;
@@ -3,9 +3,9 @@ package com.drinkool.entities;
import com.drinkool.models.ReviewModel; import com.drinkool.models.ReviewModel;
import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.QuarkusTest;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import java.util.UUID;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.UUID;
@QuarkusTest @QuarkusTest
public class ReviewEntityTest { public class ReviewEntityTest {
@@ -21,15 +21,37 @@ public class ReviewEntityTest {
ReviewModel inputModel = new ReviewModel(5, "Món ăn tuyệt vời!"); ReviewModel inputModel = new ReviewModel(5, "Món ăn tuyệt vời!");
// 2. Thực thi (Act) // 2. Thực thi (Act)
ReviewEntity savedReview = ReviewEntity.create(testReviewerId, testEateryId, inputModel); ReviewEntity savedReview = ReviewEntity.create(
testReviewerId,
testEateryId,
inputModel
);
// 3. Kiểm chứng (Assert) // 3. Kiểm chứng (Assert)
Assertions.assertNotNull(savedReview, "Thực thể Review sau khi tạo không được null"); Assertions.assertNotNull(
Assertions.assertEquals(testReviewerId, savedReview.reviewerId, "Reviewer ID không khớp"); savedReview,
Assertions.assertEquals(testEateryId, savedReview.eateryId, "Eatery ID không khớp"); "Thực thể Review sau khi tạo không được null"
);
Assertions.assertEquals(
testReviewerId,
savedReview.reviewerId,
"Reviewer ID không khớp"
);
Assertions.assertEquals(
testEateryId,
savedReview.eateryId,
"Eatery ID không khớp"
);
Assertions.assertEquals(5, savedReview.rating, "Rating không khớp"); Assertions.assertEquals(5, savedReview.rating, "Rating không khớp");
Assertions.assertEquals("Món ăn tuyệt vời!", savedReview.comment, "Comment không khớp"); Assertions.assertEquals(
"Món ăn tuyệt vời!",
savedReview.comment,
"Comment không khớp"
);
Assertions.assertNotNull(savedReview.id, "ID phải được tự động sinh ra sau khi persist"); Assertions.assertNotNull(
savedReview.id,
"ID phải được tự động sinh ra sau khi persist"
);
} }
} }
@@ -29,6 +29,4 @@ public class InventoryServiceTest {
assertEquals(1, InventoryItemEntity.find("name", name).count()); assertEquals(1, InventoryItemEntity.find("name", name).count());
} }
} }
@@ -35,7 +35,8 @@ public class ReviewServiceTest {
.body(input) .body(input)
.when() .when()
.post("/api/review/create") .post("/api/review/create")
.then().statusCode(201); .then()
.statusCode(201);
assertEquals(1, ReviewEntity.find("reviewerId", reviewerId).count()); assertEquals(1, ReviewEntity.find("reviewerId", reviewerId).count());
} }