From bcbda39ed4bb39a2aa2a2f9d25e056a193e065e8 Mon Sep 17 00:00:00 2001 From: TakahashiNguyen Date: Tue, 31 Mar 2026 13:15:39 +0000 Subject: [PATCH 1/3] feat(k8s): init (#13) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/13 --- .releaserc.json | 2 +- .../services/AuthenticationService.java | 33 ++--- .../src/main/resources/application.properties | 1 - .../services/AuthenticationServiceTest.java | 17 +-- gateway-service/pom.xml | 8 +- .../com/drinkool/CustomerGatewayResource.java | 19 +-- .../com/drinkool/services/AccountService.java | 17 ++- .../src/main/resources/application.properties | 8 +- k8s.yaml | 116 ++++++++++++++++++ lib/src/main/java/com/drinkool/Url.java | 10 ++ 10 files changed, 179 insertions(+), 52 deletions(-) create mode 100644 k8s.yaml create mode 100644 lib/src/main/java/com/drinkool/Url.java diff --git a/.releaserc.json b/.releaserc.json index 9b65fa2..ce2856c 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -14,7 +14,7 @@ [ "@semantic-release/exec", { - "prepareCmd": "./mvnw versions:set -DnewVersion=${nextRelease.version}", + "prepareCmd": "./mvnw versions:set -DnewVersion=${nextRelease.version} && sed -i \"s|\\(image: git.demonkernel.io.vn/foodsurf/[^:]*\\):.*|\\1:${nextRelease.version}|g\" k8s.yaml", "publishCmd": "if [ \"${branch.name}\" = \"main\" ]; then ./mvnw package -Dquarkus.container-image.tag=${nextRelease.version} -DskipTests; fi" } ], diff --git a/account-service/src/main/java/com/drinkool/services/AuthenticationService.java b/account-service/src/main/java/com/drinkool/services/AuthenticationService.java index fe2cbdf..70f0bd0 100644 --- a/account-service/src/main/java/com/drinkool/services/AuthenticationService.java +++ b/account-service/src/main/java/com/drinkool/services/AuthenticationService.java @@ -1,5 +1,6 @@ package com.drinkool.services; +import com.drinkool.Url; import com.drinkool.dtos.*; import com.drinkool.entities.CustomerEntity; import jakarta.inject.Inject; @@ -7,14 +8,14 @@ import jakarta.transaction.Transactional; import jakarta.ws.rs.*; import jakarta.ws.rs.core.*; -@Path("/api") +@Path("") public class AuthenticationService { @Inject OtpService otpService; @POST - @Path("/signup") + @Path(Url.Signup) @Transactional public Response signup(Signup input) { CustomerEntity newCustomer = new CustomerEntity(); @@ -25,7 +26,7 @@ public class AuthenticationService { } @POST - @Path("/quickSignup") + @Path(Url.QuickSignup) @Transactional public Response quickSignup(QuickSignup input) { CustomerEntity newCustomer = new CustomerEntity(); @@ -36,7 +37,7 @@ public class AuthenticationService { } @POST - @Path("/login") + @Path(Url.Login) public Response login(Login input) { CustomerEntity customer = CustomerEntity.find( "phone", @@ -53,18 +54,7 @@ public class AuthenticationService { } @POST - @Path("/sms_otp") - public Response smsOtp(SmsOtp input) { - String otp = otpService.generateAndSaveOtp(input.phone); - - // Ở đây bạn sẽ gọi Kafka để gửi SMS thực tế - System.out.println("OTP cho " + input.phone + " là: " + otp); - - return Response.accepted().build(); - } - - @POST - @Path("/quicklogin") + @Path(Url.QuickLogin) public Response quickLogin(QuickLogin input) { if (otpService.verifyOtp(input.phone, input.otp)) { return Response.accepted().build(); @@ -73,4 +63,15 @@ public class AuthenticationService { .entity("InvalidOTP") .build(); } + + @POST + @Path(Url.SmsOtp) + public Response smsOtp(SmsOtp input) { + String otp = otpService.generateAndSaveOtp(input.phone); + + // Ở đây bạn sẽ gọi Kafka để gửi SMS thực tế + System.out.println("OTP cho " + input.phone + " là: " + otp); + + return Response.accepted().build(); + } } diff --git a/account-service/src/main/resources/application.properties b/account-service/src/main/resources/application.properties index 857f702..07c1a35 100644 --- a/account-service/src/main/resources/application.properties +++ b/account-service/src/main/resources/application.properties @@ -7,7 +7,6 @@ quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/postgres quarkus.hibernate-orm.database.generation=update # Docker -## URL của Gitea Registry (thường là gitea.yourdomain.com) quarkus.container-image.registry=git.demonkernel.io.vn quarkus.container-image.group=foodsurf quarkus.container-image.name=account-service diff --git a/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java b/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java index f7d15f5..4925a41 100644 --- a/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java @@ -3,6 +3,7 @@ package com.drinkool.services; import static io.restassured.RestAssured.given; import static org.junit.jupiter.api.Assertions.*; +import com.drinkool.Url; import com.drinkool.dtos.*; import com.drinkool.entities.CustomerEntity; import io.quarkus.test.junit.QuarkusTest; @@ -31,7 +32,7 @@ public class AuthenticationServiceTest { .contentType(ContentType.JSON) .body(input) .when() - .post("/api/signup") + .post(Url.Signup) .then() .statusCode(201); @@ -49,7 +50,7 @@ public class AuthenticationServiceTest { .contentType(ContentType.JSON) .body(input) .when() - .post("/api/quickSignup") + .post(Url.QuickSignup) .then() .statusCode(201); @@ -68,7 +69,7 @@ public class AuthenticationServiceTest { given() .contentType(ContentType.JSON) .body(signupData) - .post("/api/signup") + .post(Url.Signup) .then() .statusCode(201); @@ -81,7 +82,7 @@ public class AuthenticationServiceTest { .contentType(ContentType.JSON) .body(loginInput) .when() - .post("/api/login") + .post(Url.Login) .then() .statusCode(202); } @@ -97,7 +98,7 @@ public class AuthenticationServiceTest { given() .contentType(ContentType.JSON) .body(signupData) - .post("/api/signup") + .post(Url.Signup) .then() .statusCode(201); @@ -109,7 +110,7 @@ public class AuthenticationServiceTest { .contentType(ContentType.JSON) .body(loginInput) .when() - .post("/api/login") + .post(Url.Login) .then() .statusCode(400); // BadRequestException } @@ -124,7 +125,7 @@ public class AuthenticationServiceTest { .contentType(ContentType.JSON) .body(input) .when() - .post("/api/sms_otp") + .post(Url.SmsOtp) .then() .statusCode(202); @@ -143,7 +144,7 @@ public class AuthenticationServiceTest { .contentType(ContentType.JSON) .body(input) .when() - .post("/api/quicklogin") + .post(Url.QuickLogin) .then() .statusCode(401); } diff --git a/gateway-service/pom.xml b/gateway-service/pom.xml index 592580f..df5aec2 100644 --- a/gateway-service/pom.xml +++ b/gateway-service/pom.xml @@ -48,10 +48,6 @@ lib ${project.version} - - io.quarkus - quarkus-redis-client - io.quarkus quarkus-rest-jackson @@ -64,6 +60,10 @@ io.quarkus quarkus-rest + + io.quarkus + quarkus-container-image-docker + io.quarkus quarkus-rest-client-jackson diff --git a/gateway-service/src/main/java/com/drinkool/CustomerGatewayResource.java b/gateway-service/src/main/java/com/drinkool/CustomerGatewayResource.java index 3e9ad32..28ebcc0 100644 --- a/gateway-service/src/main/java/com/drinkool/CustomerGatewayResource.java +++ b/gateway-service/src/main/java/com/drinkool/CustomerGatewayResource.java @@ -2,7 +2,6 @@ package com.drinkool; import com.drinkool.dtos.*; import com.drinkool.services.AccountService; -import io.quarkus.redis.datasource.RedisDataSource; import io.smallrye.mutiny.Uni; import jakarta.inject.Inject; import jakarta.ws.rs.*; @@ -16,28 +15,14 @@ public class CustomerGatewayResource { @RestClient AccountService accountService; - @Inject - RedisDataSource redisDataSource; - @POST - @Path("/signup") + @Path(Url.Signup) public Uni proxySignup(Signup input) { - String otpVerifiedKey = "otp:verified:" + input.phone; - var valueCmd = redisDataSource.value(String.class); - - if (valueCmd.get(otpVerifiedKey) == null) { - return Uni.createFrom().item( - Response.status(Response.Status.FORBIDDEN) - .entity("Phone not verified") - .build() - ); - } - return accountService.signup(input); } @POST - @Path("/login") + @Path(Url.Login) public Uni proxyLogin(Login input) { return accountService.login(input); } diff --git a/gateway-service/src/main/java/com/drinkool/services/AccountService.java b/gateway-service/src/main/java/com/drinkool/services/AccountService.java index 79befad..b58b552 100644 --- a/gateway-service/src/main/java/com/drinkool/services/AccountService.java +++ b/gateway-service/src/main/java/com/drinkool/services/AccountService.java @@ -1,5 +1,6 @@ package com.drinkool.services; +import com.drinkool.Url; import com.drinkool.dtos.*; import io.smallrye.mutiny.Uni; import jakarta.ws.rs.*; @@ -7,17 +8,25 @@ import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; @RegisterRestClient(configKey = "account") -@Path("/api") +@Path("") public interface AccountService { @POST - @Path("/signup") + @Path(Url.Signup) Uni signup(Signup input); @POST - @Path("/quickSignup") + @Path(Url.QuickSignup) Uni quickSignup(QuickSignup input); @POST - @Path("/login") + @Path(Url.Login) Uni login(Login input); + + @POST + @Path(Url.QuickLogin) + Uni quickLogin(QuickSignup input); + + @POST + @Path(Url.SmsOtp) + Uni smsOtp(SmsOtp input); } diff --git a/gateway-service/src/main/resources/application.properties b/gateway-service/src/main/resources/application.properties index 6993984..c52eb42 100644 --- a/gateway-service/src/main/resources/application.properties +++ b/gateway-service/src/main/resources/application.properties @@ -1 +1,7 @@ -quarkus.rest-client.account.url=http://localhost:502 \ No newline at end of file +# Docker +quarkus.container-image.registry=git.demonkernel.io.vn +quarkus.container-image.group=foodsurf +quarkus.container-image.name=gateway-service +quarkus.container-image.push=true +quarkus.container-image.build=true +quarkus.container-image.builder=docker diff --git a/k8s.yaml b/k8s.yaml new file mode 100644 index 0000000..4487135 --- /dev/null +++ b/k8s.yaml @@ -0,0 +1,116 @@ +# 1. ACCOUNT SERVICE +apiVersion: apps/v1 +kind: Deployment +metadata: + name: account-service +spec: + replicas: 1 + selector: + matchLabels: + app: account-service + template: + metadata: + labels: + app: account-service + spec: + containers: + - name: account-service + image: git.demonkernel.io.vn/foodsurf/account-service:latest + ports: + - containerPort: 8080 + env: + - name: QUARKUS_REDIS_HOST + value: "redis-service" +--- +apiVersion: v1 +kind: Service +metadata: + name: account-service +spec: + selector: + app: account-service + ports: + - port: 80 + targetPort: 8080 +--- +# 2. GATEWAY SERVICE +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gateway-deploy +spec: + replicas: 1 + selector: + matchLabels: + app: gateway + template: + metadata: + labels: + app: gateway + spec: + containers: + - name: gateway + image: git.demonkernel.io.vn/foodsurf/gateway-service:latest + ports: + - containerPort: 8080 + env: + - name: QUARKUS_REST_CLIENT_ACCOUNT_URL + value: "http://account-service" +--- +apiVersion: v1 +kind: Service +metadata: + name: gateway-service +spec: + type: NodePort + selector: + app: gateway + ports: + - port: 80 + targetPort: 8080 + nodePort: 39080 +--- +# 3. REDIS +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-deploy +spec: + selector: + matchLabels: + app: redis + template: + metadata: + labels: + app: redis + spec: + containers: + - name: redis + image: redis:alpine + ports: + - containerPort: 6379 + resources: + limits: + cpu: "100m" + memory: "128Mi" + requests: + cpu: "20m" + memory: "64Mi" + command: + [ + "redis-server", + "--maxmemory", + "96mb", + "--maxmemory-policy", + "allkeys-lru", + ] +--- +apiVersion: v1 +kind: Service +metadata: + name: redis-service +spec: + selector: + app: redis + ports: + - port: 6379 diff --git a/lib/src/main/java/com/drinkool/Url.java b/lib/src/main/java/com/drinkool/Url.java new file mode 100644 index 0000000..9eb1de6 --- /dev/null +++ b/lib/src/main/java/com/drinkool/Url.java @@ -0,0 +1,10 @@ +package com.drinkool; + +public class Url { + + public static final String Signup = "/signup"; + public static final String QuickSignup = "/quick_signup"; + public static final String Login = "/login"; + public static final String QuickLogin = "/quick_login"; + public static final String SmsOtp = "/sms_otp"; +} From 5a7b70145c5513e890e7c0a1605b786c4bbb0203 Mon Sep 17 00:00:00 2001 From: TranHuuDanh Date: Wed, 1 Apr 2026 08:20:41 +0000 Subject: [PATCH 2/3] feature/danh-dev-new-branch-yeu-cau-viet-anh (#14) Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Co-authored-by: TranHuuDanh Co-authored-by: TakahashiNguyen Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/backend/pulls/14 Reviewed-by: TakahashiNguyen Co-authored-by: TranHuuDanh Co-committed-by: TranHuuDanh --- .../drinkool/entities/CustomerEntityTest.java | 46 +++++ .../com/drinkool/models/UserModelTest.java | 193 ++++++++++-------- .../services/AuthenticationServiceTest.java | 3 +- .../com/drinkool/services/OtpServiceTest.java | 75 +++++++ .../drinkool/utils/PhoneValidatorTest.java | 41 ++++ .../com/drinkool/entities/MenuItemEntity.java | 2 +- .../entities/InventoryItemEntityTest.java | 44 ++++ .../drinkool/entities/MenuItemEntityTest.java | 58 ++++++ .../MenuItemIngredientEntityTest.java | 74 ++++--- .../drinkool/entities/ReviewEntityTest.java | 35 ++++ .../services/InventoryServiceTest.java | 2 + .../drinkool/services/ReviewServiceTest.java | 2 +- .../src/test/resources/application.properties | 2 +- .../java/com/drinkool/models/ReviewModel.java | 4 +- 14 files changed, 448 insertions(+), 133 deletions(-) create mode 100644 account-service/src/test/java/com/drinkool/entities/CustomerEntityTest.java create mode 100644 account-service/src/test/java/com/drinkool/services/OtpServiceTest.java create mode 100644 account-service/src/test/java/com/drinkool/utils/PhoneValidatorTest.java create mode 100644 eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java create mode 100644 eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java create mode 100644 eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java diff --git a/account-service/src/test/java/com/drinkool/entities/CustomerEntityTest.java b/account-service/src/test/java/com/drinkool/entities/CustomerEntityTest.java new file mode 100644 index 0000000..2bac81d --- /dev/null +++ b/account-service/src/test/java/com/drinkool/entities/CustomerEntityTest.java @@ -0,0 +1,46 @@ +package com.drinkool.entities; + +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class CustomerEntityTest { + + @Inject + EntityManager entityManager; + + @Test + @Transactional + public void testCustomerPersistence() { + // 1. Khởi tạo đúng Entity (CustomerEntity chứ không phải CustomerEntityTest) + CustomerEntity customer = new CustomerEntity(); + + // Gán đúng biến name, phone và hashedPassword (các trường kế thừa từ UserModel) + customer.name = "Nguyen Van A"; + customer.phone = "+84987654321"; + customer.hashedPassword = "dummy_hashed_password"; + + // 2. Lưu vào DB + entityManager.persist(customer); + entityManager.flush(); + entityManager.clear(); + + // 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( + "SELECT c FROM CustomerEntity c WHERE c.phone = :phone", CustomerEntity.class); + query.setParameter("phone", "+84987654321"); + + // Nhận kết quả về đúng kiểu CustomerEntity + CustomerEntity savedCustomer = query.getSingleResult(); + + // 4. Assert (Kiểm chứng) + Assertions.assertNotNull(savedCustomer, "Customer không được null"); + Assertions.assertEquals("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"); + } +} \ No newline at end of file diff --git a/account-service/src/test/java/com/drinkool/models/UserModelTest.java b/account-service/src/test/java/com/drinkool/models/UserModelTest.java index ad305cf..0e38f93 100644 --- a/account-service/src/test/java/com/drinkool/models/UserModelTest.java +++ b/account-service/src/test/java/com/drinkool/models/UserModelTest.java @@ -2,120 +2,135 @@ package com.drinkool.models; import static org.junit.jupiter.api.Assertions.*; -import com.drinkool.entities.CustomerEntity; -import io.quarkus.test.TestTransaction; import io.quarkus.test.junit.QuarkusTest; -import jakarta.persistence.*; +import jakarta.persistence.Entity; +import jakarta.persistence.Table; import jakarta.transaction.Transactional; import jakarta.ws.rs.BadRequestException; -import java.util.*; +import java.util.Random; import org.junit.jupiter.api.Test; @Entity -@Table +@Table(name = "test_users") class TestUserEntity extends UserModel {} @QuarkusTest public class UserModelTest { - @Test - @Transactional - public void testSignupSuccess() { - //dang nhap thanh cong - TestUserEntity user = new TestUserEntity(); - String phone = - "+8477" + String.format("%07d", (new Random()).nextInt(10000000)); - String password = "02092006Danh"; - user.signup("Tran Huu Danh", phone, password); + // Helper method để tạo số điện thoại ngẫu nhiên hợp lệ + private String generateValidPhone() { + return "+8477" + String.format("%07d", (new Random()).nextInt(10000000)); + } - assertNotNull(user.id, "ID not null after persist"); - assertEquals("Tran Huu Danh", user.name); - assertEquals(phone, user.phone); - // assertNotNull(user.hashedPassword, "password phai hash"); + // 1. Test case: Đăng ký thành công (đầy đủ tham số) + @Test + @Transactional + public void testSignupSuccess() { + TestUserEntity user = new TestUserEntity(); + String phone = generateValidPhone(); + String password = "02092006Danh"; + + user.signup("Tran Huu Danh", phone, password); - TestUserEntity savedUser = TestUserEntity.find( - "phone", - phone - ).firstResult(); - assertNotNull(savedUser); - } + assertNotNull(user.id, "ID not null after persist"); + assertEquals("Tran Huu Danh", user.name); + assertEquals(phone, user.phone); + assertNotNull(user.hashedPassword, "Password phải được hash"); - // 2. Test case: Đăng ký thất bại do số điện thoại đã tồn tại - @Test - @Transactional - public void testSignupFailExistedUser() { - TestUserEntity existUser = new TestUserEntity(); - String phone = - "+8477" + String.format("%07d", (new Random()).nextInt(10000000)); - String password = "tungtungtungshahua"; - existUser.signup("Nguyen Thanh Quy", phone, password); + TestUserEntity savedUser = TestUserEntity.find("phone", phone).firstResult(); + assertNotNull(savedUser, "Phải tìm thấy user trong database"); + } - CustomerEntity newCustomer = new CustomerEntity(); - BadRequestException exception = assertThrows( - BadRequestException.class, - () -> { - newCustomer.signup("Nguyen Viet Anh", phone, "02092006Anh"); - } - ); + // 2. Test case: Đăng ký thành công (chỉ dùng số điện thoại) + @Test + @Transactional + public void testSignupOneParamSuccess() { + TestUserEntity user = new TestUserEntity(); + String phone = generateValidPhone(); + + user.signup(phone); - assertEquals("ExistedUser", exception.getMessage()); - } + 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.phone); + 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 sai định dạng - @Test - @TestTransaction - public void testSignupFailInvalidPhoneNumber() { - TestUserEntity customer = new TestUserEntity(); - String invalidPhone = "12345"; + // 3. Test case: Đăng ký thất bại do số điện thoại đã tồn tại + @Test + @Transactional + public void testSignupFailExistedUser() { + String phone = generateValidPhone(); + String password = "tungtungtungshahua"; + + // Tạo user đầu tiên + TestUserEntity existUser = new TestUserEntity(); + existUser.signup("Nguyen Thanh Quy", phone, password); - BadRequestException exception = assertThrows( - BadRequestException.class, - () -> { - customer.signup("Lam Vi Hoang", invalidPhone, "Pass123"); - } - ); + // Tạo user thứ hai với cùng số điện thoại + TestUserEntity newUser = new TestUserEntity(); + BadRequestException exception = assertThrows(BadRequestException.class, () -> { + newUser.signup("Nguyen Viet Anh", phone, "02092006Anh"); + }); - assertEquals("InvalidPhoneNumber", exception.getMessage()); - } + assertEquals("ExistedUser", exception.getMessage()); + } - @Test - @Transactional - public void testLoginSuccess() { - //dang nhap thanh cong - TestUserEntity user = new TestUserEntity(); - String phone = - "+8477" + String.format("%07d", (new Random()).nextInt(10000000)); - String password = "02092006Danh"; - user.signup("Tran Huu Danh", phone, password); + // 4. Test case: Đăng ký thất bại do số điện thoại sai định dạng + @Test + @Transactional + public void testSignupFailInvalidPhoneNumber() { + TestUserEntity user = new TestUserEntity(); + String invalidPhone = "12345"; - Boolean loginResult = user.login(password); + BadRequestException exception = assertThrows(BadRequestException.class, () -> { + user.signup("Lam Vi Hoang", invalidPhone, "Pass123"); + }); - assertTrue(loginResult); - } + assertEquals("InvalidPhoneNumber", exception.getMessage()); + } - @Test - @Transactional - public void testLoginFailWrongPassword() { - //dang nhap that bai - TestUserEntity user = new TestUserEntity(); - String phone = - "+8477" + String.format("%07d", (new Random()).nextInt(10000000)); - String truePassword = "02092006Danh"; - String wrongPassword = "02092006danhh"; + // 5. Test case: Đăng nhập thành công + @Test + @Transactional + public void testLoginSuccess() { + TestUserEntity user = new TestUserEntity(); + String phone = generateValidPhone(); + String password = "02092006Danh"; + + user.signup("Tran Huu Danh", phone, password); - user.signup("Tran Huu Danh", phone, truePassword); - Boolean wrongTest = user.login(wrongPassword); + boolean loginResult = user.login(password); - assertFalse(wrongTest); - } + assertTrue(loginResult, "Đăng nhập phải thành công với mật khẩu đúng"); + } - @Test - @Transactional - public void testLoginFailNullHashedPassword() { - TestUserEntity user = new TestUserEntity(); - user.hashedPassword = null; + // 6. Test case: Đăng nhập thất bại do sai mật khẩu + @Test + @Transactional + public void testLoginFailWrongPassword() { + TestUserEntity user = new TestUserEntity(); + String phone = generateValidPhone(); + String truePassword = "02092006Danh"; + String wrongPassword = "02092006danhh"; + + user.signup("Tran Huu Danh", phone, truePassword); + + boolean loginResult = user.login(wrongPassword); + + assertFalse(loginResult, "Đăng nhập phải thất bại với mật khẩu sai"); + } + + // 7. Test case: Đăng nhập thất bại do hashedPassword bị null + @Test + @Transactional + public void testLoginFailNullHashedPassword() { + TestUserEntity user = new TestUserEntity(); + user.hashedPassword = null; // Cố tình set null để test lỗi + + boolean loginResult = user.login("anhdomixi"); + + assertFalse(loginResult, "Đăng nhập phải thất bại nếu hashedPassword là null"); + } - boolean loginResult = user.login("anhdomixi"); - assertFalse(loginResult); - } } diff --git a/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java b/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java index 4925a41..162f2c2 100644 --- a/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java @@ -13,13 +13,14 @@ import org.junit.jupiter.api.Test; @QuarkusTest public class AuthenticationServiceTest { - + private Random random = new Random(); private String generateRandomPhone() { return "+8477" + String.format("%07d", random.nextInt(10000000)); } + @Test void testSignup() { String phone = generateRandomPhone(); diff --git a/account-service/src/test/java/com/drinkool/services/OtpServiceTest.java b/account-service/src/test/java/com/drinkool/services/OtpServiceTest.java new file mode 100644 index 0000000..f4a9c08 --- /dev/null +++ b/account-service/src/test/java/com/drinkool/services/OtpServiceTest.java @@ -0,0 +1,75 @@ +package com.drinkool.services; + +import static org.junit.jupiter.api.Assertions.*; + +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; +import java.util.Random; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class OtpServiceTest { + + @Inject + OtpService otpService; + + // 1. Test case: Tạo và lưu OTP thành công + @Test + public void testGenerateAndSaveOtp() { + String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); + String otp = otpService.generateAndSaveOtp(phone); + + assertNotNull(otp, "OTP sinh ra không được null"); + assertEquals(6, otp.length(), "OTP phải có độ dài đúng 6 ký tự"); + assertTrue(otp.matches("\\d{6}"), "OTP chỉ được chứa các chữ số"); + } + + // 2. Test case: Xác thực OTP thành công + @Test + public void testVerifyOtpSuccess() { + String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); + String generatedOtp = otpService.generateAndSaveOtp(phone); + + // Xác thực với OTP vừa tạo ra + boolean verifyResult = otpService.verifyOtp(phone, generatedOtp); + + assertTrue(verifyResult, "Xác thực phải thành công với OTP đúng"); + } + + // 3. Test case: Xác thực thất bại do sai mã OTP + @Test + public void testVerifyOtpFailWrongOtp() { + String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); + otpService.generateAndSaveOtp(phone); // Tạo OTP nhưng không dùng + + String wrongOtp = "999999"; // Giả sử mã sai + boolean verifyResult = otpService.verifyOtp(phone, wrongOtp); + + assertFalse(verifyResult, "Xác thực phải thất bại khi truyền sai mã OTP"); + } + + // 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 + public void testVerifyOtpFailNotExists() { + 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 + 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"); + } + + // 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 + public void testVerifyOtpConsumedAfterSuccess() { + String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); + String generatedOtp = otpService.generateAndSaveOtp(phone); + + // Lần 1: Xác thực thành công + assertTrue(otpService.verifyOtp(phone, generatedOtp)); + + // 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); + assertFalse(secondVerifyResult, "OTP không được phép tái sử dụng sau khi đã verify thành công"); + } +} \ No newline at end of file diff --git a/account-service/src/test/java/com/drinkool/utils/PhoneValidatorTest.java b/account-service/src/test/java/com/drinkool/utils/PhoneValidatorTest.java new file mode 100644 index 0000000..c35bcdd --- /dev/null +++ b/account-service/src/test/java/com/drinkool/utils/PhoneValidatorTest.java @@ -0,0 +1,41 @@ +package com.drinkool.utils; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class PhoneValidatorTest { + + @Test + public void testValidVietnamesePhoneNumbers() { + // 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(PhoneValidator.isValidInternationalPhone("+84987654321")); + Assertions.assertTrue(PhoneValidator.isValidInternationalPhone("84987654321")); + } + + @Test + public void testValidInternationalPhoneNumbers() { + // Số điện thoại quốc tế hợp lệ (Ví dụ: Mỹ +1) + Assertions.assertTrue(PhoneValidator.isValidInternationalPhone("+14155552671")); + } + + @Test + public void testInvalidPhoneNumbers() { + // Chuỗi không phải số điện thoại + Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("not-a-phone-number")); + + // Số điện thoại quá ngắn hoặc sai định dạng + Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("123")); + Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("099999999999999")); + + // Chuỗi rỗng + Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("")); + } + + @Test + public void testNullPhoneNumber() { + // Cố tình truyền null để xem hàm xử lý thế nào + // Lưu ý: Đọc thêm phần "Mẹo nhỏ" bên dưới để pass được test này + Assertions.assertFalse(PhoneValidator.isValidInternationalPhone(null)); + } +} \ No newline at end of file diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java index 81da14b..a1091df 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java @@ -47,7 +47,7 @@ public class MenuItemEntity extends BaseEntity { menu.name = name; menu.price = price; - + menu.persist(); return menu; diff --git a/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java new file mode 100644 index 0000000..6544fab --- /dev/null +++ b/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java @@ -0,0 +1,44 @@ +package com.drinkool.entities; + +import io.quarkus.test.junit.QuarkusTest; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class InventoryItemEntityTest { + + @Test + @Transactional + public void testCreateInventoryItem() { + // 1. Chuẩn bị dữ liệu (Lưu ý: Không còn biến quantity nữa) + String name = "Trà sữa truyền thống"; + String unit = "Ly"; + + // 2. Gọi hàm static create (Không dùng new hay hàm add nữa) + // Hàm này vừa tạo object, vừa gán data, vừa gọi persist() luôn + InventoryItemEntity item = InventoryItemEntity.create(name, unit); + + // 3. Kiểm chứng + Assertions.assertNotNull(item, "Entity tạo ra không được null"); + Assertions.assertEquals(name, item.name, "Tên 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"); + } + + @Test + @Transactional + public void testCreateWithDefaultUnit() { + // 1. Chuẩn bị dữ liệu + String name = "Trân châu đen"; + + // 2. Gọi hàm static create rút gọn (chỉ truyền name, unit sẽ tự là "unit") + InventoryItemEntity item = InventoryItemEntity.create(name); + + // 3. Kiểm chứng + Assertions.assertNotNull(item, "Entity tạo ra không được null"); + 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.assertNotNull(item.id, "ID phải được sinh ra tự động sau khi persist"); + } +} \ No newline at end of file diff --git a/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java new file mode 100644 index 0000000..24adf80 --- /dev/null +++ b/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java @@ -0,0 +1,58 @@ +package com.drinkool.entities; + +import static org.junit.jupiter.api.Assertions.*; + +import io.quarkus.test.junit.QuarkusTest; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.Test; + +@QuarkusTest +public class MenuItemEntityTest { + + @Test + @Transactional + public void testCreateMenuItemSuccessfully() { + // 1. Chuẩn bị dữ liệu (Arrange) + String name = "Cà phê sữa đá"; + double price = 29000.0; + + // 2. Thực thi (Act) - Gọi hàm tĩnh create + MenuItemEntity menuItem = MenuItemEntity.create(name, price); + + // 3. Kiểm chứng (Assert) + assertNotNull(menuItem, "Thực thể MenuItem không được null"); + 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"); + 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"); + } + + @Test + @Transactional + public void testAddIngredientSuccessfully() { + // 1. Chuẩn bị dữ liệu (Arrange) + // Tạo món ăn + 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) + 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 + + // 2. Thực thi (Act) - Thêm nguyên liệu vào món ăn + menuItem.addIngredient(inventoryItem, requiredQty); + + // 3. Kiểm chứng (Assert) + // 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"); + 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 + MenuItemIngredientEntity addedIngredient = menuItem.ingredients.get(0); + + assertNotNull(addedIngredient.id, "ID của Entity trung gian phải được sinh ra"); + 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"); + } +} \ No newline at end of file diff --git a/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java index 75624ba..b1252dc 100644 --- a/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java +++ b/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java @@ -9,50 +9,48 @@ import org.junit.jupiter.api.Test; @QuarkusTest public class MenuItemIngredientEntityTest { - @Test - @Transactional - void testCreate_ShouldPersistIngredientSuccessfully() { - // 1. Chuẩn bị dữ liệu giả định + @Test + @Transactional + void testCreate_ShouldPersistIngredientSuccessfully() { + // 1. Chuẩn bị dữ liệu giả định - String menuItemName = "Milk Tea"; - double menuItemPrice = 40; + String menuItemName = "Milk Tea"; + double menuItemPrice = 40; - MenuItemEntity menuItem = MenuItemEntity.create( - menuItemName, - menuItemPrice - ); + MenuItemEntity menuItem = MenuItemEntity.create( + menuItemName, + menuItemPrice + ); - String inventoryItemName = "Water"; - double inventoryItemQuantity = 10; - String inventoryItemUnit = "l"; + String inventoryItemName = "Water"; + int inventoryItemQuantity = 10; // Đổi thành int cho khớp với kiểu của EateryInventoryItemEntity + String inventoryItemUnit = "l"; - EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create( - inventoryItemName, - inventoryItemQuantity, - inventoryItemUnit - ); + // 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); + // 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; - // 2. Gọi hàm static create cần test - MenuItemIngredientEntity createdIngredient = - MenuItemIngredientEntity.create( - menuItem, - inventoryItem, - requiredQuantity - ); + // 2. Gọi hàm static create cần test + MenuItemIngredientEntity createdIngredient = + MenuItemIngredientEntity.create( + menuItem, + inventoryItem, + requiredQuantity + ); - // 3. Kiểm tra kết quả - assertNotNull(createdIngredient.id, "ID không được null sau khi persist"); + // 3. Kiểm tra kết quả + assertNotNull(createdIngredient.id, "ID không được null sau khi persist"); - // Truy vấn lại từ Database để đảm bảo dữ liệu đã được lưu đúng - MenuItemIngredientEntity savedEntity = MenuItemIngredientEntity.findById( - createdIngredient.id - ); + // Truy vấn lại từ Database để đảm bảo dữ liệu đã được lưu đúng + MenuItemIngredientEntity savedEntity = MenuItemIngredientEntity.findById( + createdIngredient.id + ); - assertNotNull(savedEntity); - assertEquals(menuItem.id, savedEntity.menuItem.id); - assertEquals(inventoryItem.id, savedEntity.inventoryItem.id); - assertEquals(requiredQuantity, savedEntity.requiredQuantity); - } -} + assertNotNull(savedEntity); + assertEquals(menuItem.id, savedEntity.menuItem.id); + assertEquals(inventoryItem.id, savedEntity.inventoryItem.id); + assertEquals(requiredQuantity, savedEntity.requiredQuantity); + } +} \ No newline at end of file diff --git a/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java new file mode 100644 index 0000000..8a956f1 --- /dev/null +++ b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java @@ -0,0 +1,35 @@ +package com.drinkool.entities; + +import com.drinkool.models.ReviewModel; +import io.quarkus.test.junit.QuarkusTest; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import java.util.UUID; + +@QuarkusTest +public class ReviewEntityTest { + + @Test + @Transactional + public void testCreateReview() { + // 1. Chuẩn bị dữ liệu (Arrange) + UUID testReviewerId = UUID.randomUUID(); + UUID testEateryId = UUID.randomUUID(); + + // Truyền trực tiếp rating và comment vào constructor của ReviewModel + ReviewModel inputModel = new ReviewModel(5, "Món ăn tuyệt vời!"); + + // 2. Thực thi (Act) + ReviewEntity savedReview = ReviewEntity.create(testReviewerId, testEateryId, inputModel); + + // 3. Kiểm chứng (Assert) + Assertions.assertNotNull(savedReview, "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("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"); + } +} \ No newline at end of file diff --git a/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java index e6e2ca8..1496b92 100644 --- a/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java @@ -29,4 +29,6 @@ public class InventoryServiceTest { assertEquals(1, InventoryItemEntity.find("name", name).count()); } + + } diff --git a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java index e1b49ae..ab0bcdf 100644 --- a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java @@ -35,7 +35,7 @@ public class ReviewServiceTest { .body(input) .when() .post("/api/review/create") - .then(); + .then().statusCode(201); assertEquals(1, ReviewEntity.find("reviewerId", reviewerId).count()); } diff --git a/eatery-service/src/test/resources/application.properties b/eatery-service/src/test/resources/application.properties index 59bc331..42128a9 100644 --- a/eatery-service/src/test/resources/application.properties +++ b/eatery-service/src/test/resources/application.properties @@ -7,4 +7,4 @@ quarkus.http.host=0.0.0.0 %test.quarkus.datasource.jdbc.url=jdbc:h2:mem:test_db;DB_CLOSE_DELAY=-1 ## Orm -%test.quarkus.hibernate-orm.database.generation=drop-and-create +%test.quarkus.hibernate-orm.database.generation=drop-and-create \ No newline at end of file diff --git a/lib/src/main/java/com/drinkool/models/ReviewModel.java b/lib/src/main/java/com/drinkool/models/ReviewModel.java index 30d20e9..58c4279 100644 --- a/lib/src/main/java/com/drinkool/models/ReviewModel.java +++ b/lib/src/main/java/com/drinkool/models/ReviewModel.java @@ -13,13 +13,13 @@ public class ReviewModel extends BaseEntity { @Column public String comment; - public ReviewModel() {} - public ReviewModel(int rating, String comment) { this.rating = rating; this.comment = comment; } + public ReviewModel() {} + public ReviewModel(ReviewModel input) { this(input.rating, input.comment); } From dd3c09865f1dd26a123b988ce848265808158ffe Mon Sep 17 00:00:00 2001 From: gitea-actions Date: Wed, 1 Apr 2026 08:29:21 +0000 Subject: [PATCH 3/3] chore: release [ci skip] --- .../drinkool/entities/CustomerEntityTest.java | 72 +++--- .../com/drinkool/models/UserModelTest.java | 206 ++++++++++-------- .../services/AuthenticationServiceTest.java | 3 +- .../com/drinkool/services/OtpServiceTest.java | 111 +++++----- .../drinkool/utils/PhoneValidatorTest.java | 74 ++++--- .../com/drinkool/entities/MenuItemEntity.java | 2 +- .../entities/InventoryItemEntityTest.java | 68 +++--- .../drinkool/entities/MenuItemEntityTest.java | 110 ++++++---- .../MenuItemIngredientEntityTest.java | 76 ++++--- .../drinkool/entities/ReviewEntityTest.java | 66 ++++-- .../services/InventoryServiceTest.java | 2 - .../drinkool/services/ReviewServiceTest.java | 3 +- 12 files changed, 451 insertions(+), 342 deletions(-) diff --git a/account-service/src/test/java/com/drinkool/entities/CustomerEntityTest.java b/account-service/src/test/java/com/drinkool/entities/CustomerEntityTest.java index 2bac81d..a21454a 100644 --- a/account-service/src/test/java/com/drinkool/entities/CustomerEntityTest.java +++ b/account-service/src/test/java/com/drinkool/entities/CustomerEntityTest.java @@ -10,37 +10,47 @@ import org.junit.jupiter.api.Test; @QuarkusTest public class CustomerEntityTest { - @Inject - EntityManager entityManager; + @Inject + EntityManager entityManager; - @Test - @Transactional - public void testCustomerPersistence() { - // 1. Khởi tạo đúng Entity (CustomerEntity chứ không phải CustomerEntityTest) - CustomerEntity customer = new CustomerEntity(); - - // Gán đúng biến name, phone và hashedPassword (các trường kế thừa từ UserModel) - customer.name = "Nguyen Van A"; - customer.phone = "+84987654321"; - customer.hashedPassword = "dummy_hashed_password"; - - // 2. Lưu vào DB - entityManager.persist(customer); - entityManager.flush(); - entityManager.clear(); + @Test + @Transactional + public void testCustomerPersistence() { + // 1. Khởi tạo đúng Entity (CustomerEntity chứ không phải CustomerEntityTest) + CustomerEntity customer = new 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( - "SELECT c FROM CustomerEntity c WHERE c.phone = :phone", CustomerEntity.class); - query.setParameter("phone", "+84987654321"); - - // Nhận kết quả về đúng kiểu CustomerEntity - CustomerEntity savedCustomer = query.getSingleResult(); + // Gán đúng biến name, phone và hashedPassword (các trường kế thừa từ UserModel) + customer.name = "Nguyen Van A"; + customer.phone = "+84987654321"; + customer.hashedPassword = "dummy_hashed_password"; - // 4. Assert (Kiểm chứng) - Assertions.assertNotNull(savedCustomer, "Customer không được null"); - Assertions.assertEquals("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"); - } -} \ No newline at end of file + // 2. Lưu vào DB + entityManager.persist(customer); + entityManager.flush(); + entityManager.clear(); + + // 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( + "SELECT c FROM CustomerEntity c WHERE c.phone = :phone", + CustomerEntity.class + ); + query.setParameter("phone", "+84987654321"); + + // Nhận kết quả về đúng kiểu CustomerEntity + CustomerEntity savedCustomer = query.getSingleResult(); + + // 4. Assert (Kiểm chứng) + Assertions.assertNotNull(savedCustomer, "Customer không được null"); + Assertions.assertEquals( + "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"); + } +} diff --git a/account-service/src/test/java/com/drinkool/models/UserModelTest.java b/account-service/src/test/java/com/drinkool/models/UserModelTest.java index 0e38f93..6073c7d 100644 --- a/account-service/src/test/java/com/drinkool/models/UserModelTest.java +++ b/account-service/src/test/java/com/drinkool/models/UserModelTest.java @@ -17,120 +17,134 @@ class TestUserEntity extends UserModel {} @QuarkusTest public class UserModelTest { - // Helper method để tạo số điện thoại ngẫu nhiên hợp lệ - private String generateValidPhone() { - return "+8477" + String.format("%07d", (new Random()).nextInt(10000000)); - } + // Helper method để tạo số điện thoại ngẫu nhiên hợp lệ + private String generateValidPhone() { + return "+8477" + String.format("%07d", (new Random()).nextInt(10000000)); + } - // 1. Test case: Đăng ký thành công (đầy đủ tham số) - @Test - @Transactional - public void testSignupSuccess() { - TestUserEntity user = new TestUserEntity(); - String phone = generateValidPhone(); - String password = "02092006Danh"; - - user.signup("Tran Huu Danh", phone, password); + // 1. Test case: Đăng ký thành công (đầy đủ tham số) + @Test + @Transactional + public void testSignupSuccess() { + TestUserEntity user = new TestUserEntity(); + String phone = generateValidPhone(); + String password = "02092006Danh"; - assertNotNull(user.id, "ID not null after persist"); - assertEquals("Tran Huu Danh", user.name); - assertEquals(phone, user.phone); - assertNotNull(user.hashedPassword, "Password phải được hash"); + user.signup("Tran Huu Danh", phone, password); - TestUserEntity savedUser = TestUserEntity.find("phone", phone).firstResult(); - assertNotNull(savedUser, "Phải tìm thấy user trong database"); - } + assertNotNull(user.id, "ID not null after persist"); + assertEquals("Tran Huu Danh", user.name); + assertEquals(phone, user.phone); + assertNotNull(user.hashedPassword, "Password phải được hash"); - // 2. Test case: Đăng ký thành công (chỉ dùng số điện thoại) - @Test - @Transactional - public void testSignupOneParamSuccess() { - TestUserEntity user = new TestUserEntity(); - String phone = generateValidPhone(); - - user.signup(phone); + TestUserEntity savedUser = TestUserEntity.find( + "phone", + phone + ).firstResult(); + assertNotNull(savedUser, "Phải tìm thấy user trong database"); + } - 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.phone); - assertNotNull(user.hashedPassword, "Password tự động phải được tạo và hash"); - } + // 2. Test case: Đăng ký thành công (chỉ dùng số điện thoại) + @Test + @Transactional + public void testSignupOneParamSuccess() { + TestUserEntity user = new TestUserEntity(); + String phone = generateValidPhone(); - // 3. Test case: Đăng ký thất bại do số điện thoại đã tồn tại - @Test - @Transactional - public void testSignupFailExistedUser() { - String phone = generateValidPhone(); - String password = "tungtungtungshahua"; - - // Tạo user đầu tiên - TestUserEntity existUser = new TestUserEntity(); - existUser.signup("Nguyen Thanh Quy", phone, password); + user.signup(phone); - // Tạo user thứ hai với cùng số điện thoại - TestUserEntity newUser = new TestUserEntity(); - BadRequestException exception = assertThrows(BadRequestException.class, () -> { - newUser.signup("Nguyen Viet Anh", phone, "02092006Anh"); - }); + 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.phone); + assertNotNull( + user.hashedPassword, + "Password tự động phải được tạo và hash" + ); + } - assertEquals("ExistedUser", exception.getMessage()); - } + // 3. Test case: Đăng ký thất bại do số điện thoại đã tồn tại + @Test + @Transactional + public void testSignupFailExistedUser() { + String phone = generateValidPhone(); + String password = "tungtungtungshahua"; - // 4. Test case: Đăng ký thất bại do số điện thoại sai định dạng - @Test - @Transactional - public void testSignupFailInvalidPhoneNumber() { - TestUserEntity user = new TestUserEntity(); - String invalidPhone = "12345"; + // Tạo user đầu tiên + TestUserEntity existUser = new TestUserEntity(); + existUser.signup("Nguyen Thanh Quy", phone, password); - BadRequestException exception = assertThrows(BadRequestException.class, () -> { - user.signup("Lam Vi Hoang", invalidPhone, "Pass123"); - }); + // Tạo user thứ hai với cùng số điện thoại + TestUserEntity newUser = new TestUserEntity(); + BadRequestException exception = assertThrows( + BadRequestException.class, + () -> { + newUser.signup("Nguyen Viet Anh", phone, "02092006Anh"); + } + ); - assertEquals("InvalidPhoneNumber", exception.getMessage()); - } + assertEquals("ExistedUser", exception.getMessage()); + } - // 5. Test case: Đăng nhập thành công - @Test - @Transactional - public void testLoginSuccess() { - TestUserEntity user = new TestUserEntity(); - String phone = generateValidPhone(); - String password = "02092006Danh"; - - user.signup("Tran Huu Danh", phone, password); + // 4. Test case: Đăng ký thất bại do số điện thoại sai định dạng + @Test + @Transactional + public void testSignupFailInvalidPhoneNumber() { + TestUserEntity user = new TestUserEntity(); + String invalidPhone = "12345"; - boolean loginResult = user.login(password); + BadRequestException exception = assertThrows( + BadRequestException.class, + () -> { + user.signup("Lam Vi Hoang", invalidPhone, "Pass123"); + } + ); - assertTrue(loginResult, "Đăng nhập phải thành công với mật khẩu đúng"); - } + assertEquals("InvalidPhoneNumber", exception.getMessage()); + } - // 6. Test case: Đăng nhập thất bại do sai mật khẩu - @Test - @Transactional - public void testLoginFailWrongPassword() { - TestUserEntity user = new TestUserEntity(); - String phone = generateValidPhone(); - String truePassword = "02092006Danh"; - String wrongPassword = "02092006danhh"; + // 5. Test case: Đăng nhập thành công + @Test + @Transactional + public void testLoginSuccess() { + TestUserEntity user = new TestUserEntity(); + String phone = generateValidPhone(); + String password = "02092006Danh"; - user.signup("Tran Huu Danh", phone, truePassword); - - boolean loginResult = user.login(wrongPassword); + user.signup("Tran Huu Danh", phone, password); - assertFalse(loginResult, "Đăng nhập phải thất bại với mật khẩu sai"); - } + boolean loginResult = user.login(password); - // 7. Test case: Đăng nhập thất bại do hashedPassword bị null - @Test - @Transactional - public void testLoginFailNullHashedPassword() { - TestUserEntity user = new TestUserEntity(); - user.hashedPassword = null; // Cố tình set null để test lỗi + assertTrue(loginResult, "Đăng nhập phải thành công với mật khẩu đúng"); + } - boolean loginResult = user.login("anhdomixi"); - - assertFalse(loginResult, "Đăng nhập phải thất bại nếu hashedPassword là null"); - } + // 6. Test case: Đăng nhập thất bại do sai mật khẩu + @Test + @Transactional + public void testLoginFailWrongPassword() { + TestUserEntity user = new TestUserEntity(); + String phone = generateValidPhone(); + String truePassword = "02092006Danh"; + String wrongPassword = "02092006danhh"; + user.signup("Tran Huu Danh", phone, truePassword); + + boolean loginResult = user.login(wrongPassword); + + assertFalse(loginResult, "Đăng nhập phải thất bại với mật khẩu sai"); + } + + // 7. Test case: Đăng nhập thất bại do hashedPassword bị null + @Test + @Transactional + public void testLoginFailNullHashedPassword() { + TestUserEntity user = new TestUserEntity(); + user.hashedPassword = null; // Cố tình set null để test lỗi + + boolean loginResult = user.login("anhdomixi"); + + assertFalse( + loginResult, + "Đăng nhập phải thất bại nếu hashedPassword là null" + ); + } } diff --git a/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java b/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java index 162f2c2..4925a41 100644 --- a/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/AuthenticationServiceTest.java @@ -13,14 +13,13 @@ import org.junit.jupiter.api.Test; @QuarkusTest public class AuthenticationServiceTest { - + private Random random = new Random(); private String generateRandomPhone() { return "+8477" + String.format("%07d", random.nextInt(10000000)); } - @Test void testSignup() { String phone = generateRandomPhone(); diff --git a/account-service/src/test/java/com/drinkool/services/OtpServiceTest.java b/account-service/src/test/java/com/drinkool/services/OtpServiceTest.java index f4a9c08..0057f97 100644 --- a/account-service/src/test/java/com/drinkool/services/OtpServiceTest.java +++ b/account-service/src/test/java/com/drinkool/services/OtpServiceTest.java @@ -10,66 +10,77 @@ import org.junit.jupiter.api.Test; @QuarkusTest public class OtpServiceTest { - @Inject - OtpService otpService; + @Inject + OtpService otpService; - // 1. Test case: Tạo và lưu OTP thành công - @Test - public void testGenerateAndSaveOtp() { - String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); - String otp = otpService.generateAndSaveOtp(phone); + // 1. Test case: Tạo và lưu OTP thành công + @Test + public void testGenerateAndSaveOtp() { + String phone = + "+8477" + String.format("%07d", new Random().nextInt(10000000)); + String otp = otpService.generateAndSaveOtp(phone); - assertNotNull(otp, "OTP sinh ra không được null"); - assertEquals(6, otp.length(), "OTP phải có độ dài đúng 6 ký tự"); - assertTrue(otp.matches("\\d{6}"), "OTP chỉ được chứa các chữ số"); - } + assertNotNull(otp, "OTP sinh ra không được null"); + assertEquals(6, otp.length(), "OTP phải có độ dài đúng 6 ký tự"); + assertTrue(otp.matches("\\d{6}"), "OTP chỉ được chứa các chữ số"); + } - // 2. Test case: Xác thực OTP thành công - @Test - public void testVerifyOtpSuccess() { - String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); - String generatedOtp = otpService.generateAndSaveOtp(phone); + // 2. Test case: Xác thực OTP thành công + @Test + public void testVerifyOtpSuccess() { + String phone = + "+8477" + String.format("%07d", new Random().nextInt(10000000)); + String generatedOtp = otpService.generateAndSaveOtp(phone); - // Xác thực với OTP vừa tạo ra - boolean verifyResult = otpService.verifyOtp(phone, generatedOtp); + // Xác thực với OTP vừa tạo ra + boolean verifyResult = otpService.verifyOtp(phone, generatedOtp); - assertTrue(verifyResult, "Xác thực phải thành công với OTP đúng"); - } + assertTrue(verifyResult, "Xác thực phải thành công với OTP đúng"); + } - // 3. Test case: Xác thực thất bại do sai mã OTP - @Test - public void testVerifyOtpFailWrongOtp() { - String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); - otpService.generateAndSaveOtp(phone); // Tạo OTP nhưng không dùng + // 3. Test case: Xác thực thất bại do sai mã OTP + @Test + public void testVerifyOtpFailWrongOtp() { + String phone = + "+8477" + String.format("%07d", new Random().nextInt(10000000)); + otpService.generateAndSaveOtp(phone); // Tạo OTP nhưng không dùng - String wrongOtp = "999999"; // Giả sử mã sai - boolean verifyResult = otpService.verifyOtp(phone, wrongOtp); + String wrongOtp = "999999"; // Giả sử mã sai + boolean verifyResult = otpService.verifyOtp(phone, wrongOtp); - assertFalse(verifyResult, "Xác thực phải thất bại khi truyền sai mã OTP"); - } + assertFalse(verifyResult, "Xác thực phải thất bại khi truyền sai mã OTP"); + } - // 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 - public void testVerifyOtpFailNotExists() { - 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 - boolean verifyResult = otpService.verifyOtp(unverifiedPhone, "123456"); + // 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 + public void testVerifyOtpFailNotExists() { + String unverifiedPhone = + "+8499" + String.format("%07d", new Random().nextInt(10000000)); - assertFalse(verifyResult, "Xác thực phải thất bại với SĐT không có OTP trong Redis"); - } + // 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"); - // 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 - public void testVerifyOtpConsumedAfterSuccess() { - String phone = "+8477" + String.format("%07d", new Random().nextInt(10000000)); - String generatedOtp = otpService.generateAndSaveOtp(phone); + assertFalse( + verifyResult, + "Xác thực phải thất bại với SĐT không có OTP trong Redis" + ); + } - // Lần 1: Xác thực thành công - assertTrue(otpService.verifyOtp(phone, generatedOtp)); + // 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 + public void testVerifyOtpConsumedAfterSuccess() { + String phone = + "+8477" + String.format("%07d", new Random().nextInt(10000000)); + String generatedOtp = otpService.generateAndSaveOtp(phone); - // 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); - assertFalse(secondVerifyResult, "OTP không được phép tái sử dụng sau khi đã verify thành công"); - } -} \ No newline at end of file + // Lần 1: Xác thực thành công + assertTrue(otpService.verifyOtp(phone, generatedOtp)); + + // 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); + assertFalse( + secondVerifyResult, + "OTP không được phép tái sử dụng sau khi đã verify thành công" + ); + } +} diff --git a/account-service/src/test/java/com/drinkool/utils/PhoneValidatorTest.java b/account-service/src/test/java/com/drinkool/utils/PhoneValidatorTest.java index c35bcdd..10676a3 100644 --- a/account-service/src/test/java/com/drinkool/utils/PhoneValidatorTest.java +++ b/account-service/src/test/java/com/drinkool/utils/PhoneValidatorTest.java @@ -5,37 +5,49 @@ import org.junit.jupiter.api.Test; public class PhoneValidatorTest { - @Test - public void testValidVietnamesePhoneNumbers() { - // 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(PhoneValidator.isValidInternationalPhone("+84987654321")); - Assertions.assertTrue(PhoneValidator.isValidInternationalPhone("84987654321")); - } + @Test + public void testValidVietnamesePhoneNumbers() { + // 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( + PhoneValidator.isValidInternationalPhone("+84987654321") + ); + Assertions.assertTrue( + PhoneValidator.isValidInternationalPhone("84987654321") + ); + } - @Test - public void testValidInternationalPhoneNumbers() { - // Số điện thoại quốc tế hợp lệ (Ví dụ: Mỹ +1) - Assertions.assertTrue(PhoneValidator.isValidInternationalPhone("+14155552671")); - } + @Test + public void testValidInternationalPhoneNumbers() { + // Số điện thoại quốc tế hợp lệ (Ví dụ: Mỹ +1) + Assertions.assertTrue( + PhoneValidator.isValidInternationalPhone("+14155552671") + ); + } - @Test - public void testInvalidPhoneNumbers() { - // Chuỗi không phải số điện thoại - Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("not-a-phone-number")); - - // Số điện thoại quá ngắn hoặc sai định dạng - Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("123")); - Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("099999999999999")); - - // Chuỗi rỗng - Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("")); - } + @Test + public void testInvalidPhoneNumbers() { + // Chuỗi không phải số điện thoại + Assertions.assertFalse( + PhoneValidator.isValidInternationalPhone("not-a-phone-number") + ); - @Test - public void testNullPhoneNumber() { - // Cố tình truyền null để xem hàm xử lý thế nào - // Lưu ý: Đọc thêm phần "Mẹo nhỏ" bên dưới để pass được test này - Assertions.assertFalse(PhoneValidator.isValidInternationalPhone(null)); - } -} \ No newline at end of file + // Số điện thoại quá ngắn hoặc sai định dạng + Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("123")); + Assertions.assertFalse( + PhoneValidator.isValidInternationalPhone("099999999999999") + ); + + // Chuỗi rỗng + Assertions.assertFalse(PhoneValidator.isValidInternationalPhone("")); + } + + @Test + public void testNullPhoneNumber() { + // Cố tình truyền null để xem hàm xử lý thế nào + // Lưu ý: Đọc thêm phần "Mẹo nhỏ" bên dưới để pass được test này + Assertions.assertFalse(PhoneValidator.isValidInternationalPhone(null)); + } +} diff --git a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java index a1091df..81da14b 100644 --- a/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java +++ b/eatery-service/src/main/java/com/drinkool/entities/MenuItemEntity.java @@ -47,7 +47,7 @@ public class MenuItemEntity extends BaseEntity { menu.name = name; menu.price = price; - + menu.persist(); return menu; diff --git a/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java index 6544fab..4aecfc0 100644 --- a/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java +++ b/eatery-service/src/test/java/com/drinkool/entities/InventoryItemEntityTest.java @@ -8,37 +8,43 @@ import org.junit.jupiter.api.Test; @QuarkusTest public class InventoryItemEntityTest { - @Test - @Transactional - public void testCreateInventoryItem() { - // 1. Chuẩn bị dữ liệu (Lưu ý: Không còn biến quantity nữa) - String name = "Trà sữa truyền thống"; - String unit = "Ly"; - - // 2. Gọi hàm static create (Không dùng new hay hàm add nữa) - // Hàm này vừa tạo object, vừa gán data, vừa gọi persist() luôn - InventoryItemEntity item = InventoryItemEntity.create(name, unit); + @Test + @Transactional + public void testCreateInventoryItem() { + // 1. Chuẩn bị dữ liệu (Lưu ý: Không còn biến quantity nữa) + String name = "Trà sữa truyền thống"; + String unit = "Ly"; - // 3. Kiểm chứng - Assertions.assertNotNull(item, "Entity tạo ra không được null"); - Assertions.assertEquals(name, item.name, "Tên 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"); - } + // 2. Gọi hàm static create (Không dùng new hay hàm add nữa) + // Hàm này vừa tạo object, vừa gán data, vừa gọi persist() luôn + InventoryItemEntity item = InventoryItemEntity.create(name, unit); - @Test - @Transactional - public void testCreateWithDefaultUnit() { - // 1. Chuẩn bị dữ liệu - String name = "Trân châu đen"; - - // 2. Gọi hàm static create rút gọn (chỉ truyền name, unit sẽ tự là "unit") - InventoryItemEntity item = InventoryItemEntity.create(name); + // 3. Kiểm chứng + Assertions.assertNotNull(item, "Entity tạo ra không được null"); + Assertions.assertEquals(name, item.name, "Tên 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" + ); + } - // 3. Kiểm chứng - Assertions.assertNotNull(item, "Entity tạo ra không được null"); - 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.assertNotNull(item.id, "ID phải được sinh ra tự động sau khi persist"); - } -} \ No newline at end of file + @Test + @Transactional + public void testCreateWithDefaultUnit() { + // 1. Chuẩn bị dữ liệu + String name = "Trân châu đen"; + + // 2. Gọi hàm static create rút gọn (chỉ truyền name, unit sẽ tự là "unit") + InventoryItemEntity item = InventoryItemEntity.create(name); + + // 3. Kiểm chứng + Assertions.assertNotNull(item, "Entity tạo ra không được null"); + 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.assertNotNull( + item.id, + "ID phải được sinh ra tự động sau khi persist" + ); + } +} diff --git a/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java index 24adf80..e6b62ac 100644 --- a/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java +++ b/eatery-service/src/test/java/com/drinkool/entities/MenuItemEntityTest.java @@ -9,50 +9,82 @@ import org.junit.jupiter.api.Test; @QuarkusTest public class MenuItemEntityTest { - @Test - @Transactional - public void testCreateMenuItemSuccessfully() { - // 1. Chuẩn bị dữ liệu (Arrange) - String name = "Cà phê sữa đá"; - double price = 29000.0; + @Test + @Transactional + public void testCreateMenuItemSuccessfully() { + // 1. Chuẩn bị dữ liệu (Arrange) + String name = "Cà phê sữa đá"; + double price = 29000.0; - // 2. Thực thi (Act) - Gọi hàm tĩnh create - MenuItemEntity menuItem = MenuItemEntity.create(name, price); + // 2. Thực thi (Act) - Gọi hàm tĩnh create + MenuItemEntity menuItem = MenuItemEntity.create(name, price); - // 3. Kiểm chứng (Assert) - assertNotNull(menuItem, "Thực thể MenuItem không được null"); - 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"); - 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"); - } + // 3. Kiểm chứng (Assert) + assertNotNull(menuItem, "Thực thể MenuItem không được null"); + 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"); + 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" + ); + } - @Test - @Transactional - public void testAddIngredientSuccessfully() { - // 1. Chuẩn bị dữ liệu (Arrange) - // Tạo món ăn - MenuItemEntity menuItem = MenuItemEntity.create("Trà sữa trân châu", 45000.0); + @Test + @Transactional + public void testAddIngredientSuccessfully() { + // 1. Chuẩn bị dữ liệu (Arrange) + // Tạo món ăn + 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) - EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create("Trân châu đen", 50, "kg"); + // 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" + ); - 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 - // 2. Thực thi (Act) - Thêm nguyên liệu vào món ăn - menuItem.addIngredient(inventoryItem, requiredQty); + // 2. Thực thi (Act) - Thêm nguyên liệu vào món ăn + menuItem.addIngredient(inventoryItem, requiredQty); - // 3. Kiểm chứng (Assert) - // 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"); - assertEquals(1, menuItem.ingredients.size(), "Phải có đúng 1 nguyên liệu trong danh sách"); + // 3. Kiểm chứng (Assert) + // 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" + ); + 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 - MenuItemIngredientEntity addedIngredient = menuItem.ingredients.get(0); - - assertNotNull(addedIngredient.id, "ID của Entity trung gian phải được sinh ra"); - 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"); - } -} \ No newline at end of file + // 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); + + assertNotNull( + addedIngredient.id, + "ID của Entity trung gian phải được sinh ra" + ); + 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" + ); + } +} diff --git a/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java index b1252dc..f9f84f8 100644 --- a/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java +++ b/eatery-service/src/test/java/com/drinkool/entities/MenuItemIngredientEntityTest.java @@ -9,48 +9,52 @@ import org.junit.jupiter.api.Test; @QuarkusTest public class MenuItemIngredientEntityTest { - @Test - @Transactional - void testCreate_ShouldPersistIngredientSuccessfully() { - // 1. Chuẩn bị dữ liệu giả định + @Test + @Transactional + void testCreate_ShouldPersistIngredientSuccessfully() { + // 1. Chuẩn bị dữ liệu giả định - String menuItemName = "Milk Tea"; - double menuItemPrice = 40; + String menuItemName = "Milk Tea"; + double menuItemPrice = 40; - MenuItemEntity menuItem = MenuItemEntity.create( - menuItemName, - menuItemPrice - ); + MenuItemEntity menuItem = MenuItemEntity.create( + menuItemName, + menuItemPrice + ); - String inventoryItemName = "Water"; - int inventoryItemQuantity = 10; // Đổi thành int cho khớp với kiểu của EateryInventoryItemEntity - String inventoryItemUnit = "l"; + String inventoryItemName = "Water"; + int inventoryItemQuantity = 10; // Đổi thành int cho khớp với kiểu của EateryInventoryItemEntity + 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 - 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! + // 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 + ); + // 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; - // 2. Gọi hàm static create cần test - MenuItemIngredientEntity createdIngredient = - MenuItemIngredientEntity.create( - menuItem, - inventoryItem, - requiredQuantity - ); + // 2. Gọi hàm static create cần test + MenuItemIngredientEntity createdIngredient = + MenuItemIngredientEntity.create( + menuItem, + inventoryItem, + requiredQuantity + ); - // 3. Kiểm tra kết quả - assertNotNull(createdIngredient.id, "ID không được null sau khi persist"); + // 3. Kiểm tra kết quả + assertNotNull(createdIngredient.id, "ID không được null sau khi persist"); - // Truy vấn lại từ Database để đảm bảo dữ liệu đã được lưu đúng - MenuItemIngredientEntity savedEntity = MenuItemIngredientEntity.findById( - createdIngredient.id - ); + // Truy vấn lại từ Database để đảm bảo dữ liệu đã được lưu đúng + MenuItemIngredientEntity savedEntity = MenuItemIngredientEntity.findById( + createdIngredient.id + ); - assertNotNull(savedEntity); - assertEquals(menuItem.id, savedEntity.menuItem.id); - assertEquals(inventoryItem.id, savedEntity.inventoryItem.id); - assertEquals(requiredQuantity, savedEntity.requiredQuantity); - } -} \ No newline at end of file + assertNotNull(savedEntity); + assertEquals(menuItem.id, savedEntity.menuItem.id); + assertEquals(inventoryItem.id, savedEntity.inventoryItem.id); + assertEquals(requiredQuantity, savedEntity.requiredQuantity); + } +} diff --git a/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java index 8a956f1..956b795 100644 --- a/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java +++ b/eatery-service/src/test/java/com/drinkool/entities/ReviewEntityTest.java @@ -3,33 +3,55 @@ package com.drinkool.entities; import com.drinkool.models.ReviewModel; import io.quarkus.test.junit.QuarkusTest; import jakarta.transaction.Transactional; +import java.util.UUID; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.util.UUID; @QuarkusTest public class ReviewEntityTest { - @Test - @Transactional - public void testCreateReview() { - // 1. Chuẩn bị dữ liệu (Arrange) - UUID testReviewerId = UUID.randomUUID(); - UUID testEateryId = UUID.randomUUID(); - - // Truyền trực tiếp rating và comment vào constructor của ReviewModel - ReviewModel inputModel = new ReviewModel(5, "Món ăn tuyệt vời!"); + @Test + @Transactional + public void testCreateReview() { + // 1. Chuẩn bị dữ liệu (Arrange) + UUID testReviewerId = UUID.randomUUID(); + UUID testEateryId = UUID.randomUUID(); - // 2. Thực thi (Act) - ReviewEntity savedReview = ReviewEntity.create(testReviewerId, testEateryId, inputModel); + // Truyền trực tiếp rating và comment vào constructor của ReviewModel + ReviewModel inputModel = new ReviewModel(5, "Món ăn tuyệt vời!"); - // 3. Kiểm chứng (Assert) - Assertions.assertNotNull(savedReview, "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("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"); - } -} \ No newline at end of file + // 2. Thực thi (Act) + ReviewEntity savedReview = ReviewEntity.create( + testReviewerId, + testEateryId, + inputModel + ); + + // 3. Kiểm chứng (Assert) + Assertions.assertNotNull( + savedReview, + "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( + "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" + ); + } +} diff --git a/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java index 1496b92..e6e2ca8 100644 --- a/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/InventoryServiceTest.java @@ -29,6 +29,4 @@ public class InventoryServiceTest { assertEquals(1, InventoryItemEntity.find("name", name).count()); } - - } diff --git a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java index ab0bcdf..69c5c34 100644 --- a/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java +++ b/eatery-service/src/test/java/com/drinkool/services/ReviewServiceTest.java @@ -35,7 +35,8 @@ public class ReviewServiceTest { .body(input) .when() .post("/api/review/create") - .then().statusCode(201); + .then() + .statusCode(201); assertEquals(1, ReviewEntity.find("reviewerId", reviewerId).count()); }