diff --git a/README.md b/README.md
index 09356b1..75c301b 100644
--- a/README.md
+++ b/README.md
@@ -254,10 +254,10 @@ curl -X PUT "http://localhost:8080/random-users/1" \
PostgreSQL
```
-### Domain Service Ports
+### Service Architecture
-- `LocalUserService`: local persistence operations (save, read, delete) backed by PostgreSQL.
-- `RemoteUserService`: external user source contract used by use cases.
+- `UserService`: domain port for local persistence operations (save, read, delete) backed by PostgreSQL. Implemented by `UserServiceImpl` in the data layer.
+- `RemoteUserService`: data-layer interface for external API adapters. Implemented by `DummyUserServiceImpl` and `RandomUserServiceImpl`.
### External Source Adapter
diff --git a/mvnw.cmd b/mvnw.cmd
index 92450f9..14aeffb 100644
--- a/mvnw.cmd
+++ b/mvnw.cmd
@@ -23,7 +23,7 @@
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
-@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+@REM MVNW_USERNAME/MVNW_PASSWORD - userDAO and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 80f07a0..7e1a68c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
2.0.4
false
**/*Application.java
- **/feature/SpringIntegrationTest.java
+ **/features/SpringIntegrationTest.java
${project.build.directory}/site/jacoco/jacoco.xml
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/converters/UserConverter.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/converters/UserConverter.java
index 5bff94e..748dac6 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/data/converters/UserConverter.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/data/converters/UserConverter.java
@@ -2,7 +2,7 @@
import com.xpeho.spring_boot_java_random_user.data.models.api.dummy.DummyUserResultDTO;
import com.xpeho.spring_boot_java_random_user.data.models.api.randomuser.RandomUserResultDTO;
-import com.xpeho.spring_boot_java_random_user.data.models.database.User;
+import com.xpeho.spring_boot_java_random_user.data.models.database.UserDAO;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import org.springframework.stereotype.Service;
@@ -10,32 +10,32 @@
@Service
public class UserConverter {
// Domain -> DAO
- public User toDao(UserEntity entity) {
- User user = new User();
- user.setId(entity.id());
- user.setGender(entity.gender());
- user.setFirstname(entity.firstname());
- user.setLastname(entity.lastname());
- user.setCivility(entity.civility());
- user.setEmail(entity.email());
- user.setPhone(entity.phone());
- user.setPicture(entity.picture());
- user.setNationality(entity.nat());
- return user;
+ public UserDAO toDao(UserEntity entity) {
+ UserDAO userDAO = new UserDAO();
+ userDAO.setId(entity.id());
+ userDAO.setGender(entity.gender());
+ userDAO.setFirstname(entity.firstname());
+ userDAO.setLastname(entity.lastname());
+ userDAO.setCivility(entity.civility());
+ userDAO.setEmail(entity.email());
+ userDAO.setPhone(entity.phone());
+ userDAO.setPicture(entity.picture());
+ userDAO.setNationality(entity.nat());
+ return userDAO;
}
// DAO -> Domain
- public UserEntity toDomain(User user) {
+ public UserEntity toDomain(UserDAO userDAO) {
return new UserEntity(
- user.getId(),
- user.getGender(),
- user.getFirstname(),
- user.getLastname(),
- user.getCivility(),
- user.getEmail(),
- user.getPhone(),
- user.getPicture(),
- user.getNationality()
+ userDAO.getId(),
+ userDAO.getGender(),
+ userDAO.getFirstname(),
+ userDAO.getLastname(),
+ userDAO.getCivility(),
+ userDAO.getEmail(),
+ userDAO.getPhone(),
+ userDAO.getPicture(),
+ userDAO.getNationality()
);
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/models/database/User.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/models/database/UserDAO.java
similarity index 98%
rename from src/main/java/com/xpeho/spring_boot_java_random_user/data/models/database/User.java
rename to src/main/java/com/xpeho/spring_boot_java_random_user/data/models/database/UserDAO.java
index bdd3a8a..5199914 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/data/models/database/User.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/data/models/database/UserDAO.java
@@ -9,7 +9,7 @@
@Entity
@Table(name = "users")
-public class User {
+public class UserDAO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
@@ -32,7 +32,7 @@ public class User {
private String nationality;
// Required by JPA
- public User() {
+ public UserDAO() {
// No initialization needed
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImpl.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImpl.java
index 76271af..c42e272 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImpl.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImpl.java
@@ -1,33 +1,48 @@
package com.xpeho.spring_boot_java_random_user.data.services;
import com.xpeho.spring_boot_java_random_user.data.converters.UserConverter;
-import com.xpeho.spring_boot_java_random_user.data.models.database.User;
+import com.xpeho.spring_boot_java_random_user.data.models.database.UserDAO;
+import com.xpeho.spring_boot_java_random_user.data.sources.api.RemoteUserService;
import com.xpeho.spring_boot_java_random_user.data.sources.database.UserRepository;
import com.xpeho.spring_boot_java_random_user.data.sources.database.UserSpecifications;
+import com.xpeho.spring_boot_java_random_user.domain.entities.PaginatedUsers;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
+import java.io.IOException;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@Service
-
-public class UserServiceImpl implements LocalUserService {
+public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final UserConverter userConverter;
+ private final Map remoteUserServices;
- public UserServiceImpl(UserRepository userRepository, UserConverter userConverter) {
+ public UserServiceImpl(
+ UserRepository userRepository,
+ UserConverter userConverter,
+ List remoteUserServices
+ ) {
this.userRepository = userRepository;
this.userConverter = userConverter;
+ this.remoteUserServices = remoteUserServices.stream()
+ .collect(Collectors.toMap(RemoteUserService::getSource, Function.identity()));
}
@Override
public List saveAll(List users) {
- List daoUsers = users.stream().map(userConverter::toDao).toList();
- Iterable saved = userRepository.saveAll(daoUsers);
+ List userDAOs = users.stream().map(userConverter::toDao).toList();
+ Iterable saved = userRepository.saveAll(userDAOs);
return StreamSupport.stream(saved.spliterator(), false)
.map(userConverter::toDomain)
.toList();
@@ -41,8 +56,8 @@ public Optional getById(long id) {
@Override
public UserEntity save(UserEntity user) {
- User savedUser = userRepository.save(userConverter.toDao(user));
- return userConverter.toDomain(savedUser);
+ UserDAO savedUserDAO = userRepository.save(userConverter.toDao(user));
+ return userConverter.toDomain(savedUserDAO);
}
@Override
@@ -51,9 +66,19 @@ public void deleteById(long id) {
}
@Override
- public List filterUsers(UserFilter filter) {
- return userRepository.findAll(UserSpecifications.byFilter(filter)).stream()
- .map(userConverter::toDomain)
- .toList();
+ public Page filterUsers(UserFilter filter, Pageable pageable) {
+ return userRepository.findAll(UserSpecifications.byFilter(filter), pageable)
+ .map(userConverter::toDomain);
+ }
+
+ @Override
+ public PaginatedUsers fetchAndSaveUsers(int page, int size, UserSource source) throws IOException {
+ RemoteUserService remoteService = remoteUserServices.get(source);
+ if (remoteService == null) {
+ throw new IllegalStateException("No remote service configured for source: " + source);
+ }
+ PaginatedUsers response = remoteService.fetchUsers(page, size);
+ saveAll(response.data());
+ return response;
}
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/services/RemoteUserService.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/RemoteUserService.java
similarity index 83%
rename from src/main/java/com/xpeho/spring_boot_java_random_user/domain/services/RemoteUserService.java
rename to src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/RemoteUserService.java
index 0945997..40ab8f5 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/services/RemoteUserService.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/RemoteUserService.java
@@ -1,4 +1,4 @@
-package com.xpeho.spring_boot_java_random_user.domain.services;
+package com.xpeho.spring_boot_java_random_user.data.sources.api;
import com.xpeho.spring_boot_java_random_user.domain.entities.PaginatedUsers;
import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/UserApiConfig.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/UserApiConfig.java
new file mode 100644
index 0000000..58fa87f
--- /dev/null
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/UserApiConfig.java
@@ -0,0 +1,67 @@
+package com.xpeho.spring_boot_java_random_user.data.sources.api;
+
+import com.xpeho.spring_boot_java_random_user.data.sources.api.dummy.DummyUserApi;
+import com.xpeho.spring_boot_java_random_user.data.sources.api.randomuser.RandomUserApi;
+import jakarta.annotation.PreDestroy;
+import okhttp3.OkHttpClient;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+@Configuration
+public class UserApiConfig {
+
+ private OkHttpClient okHttpClient;
+
+ /**
+ * Single shared OkHttpClient intentionally reused by both Retrofit instances (dummyUserRetrofit and randomUserRetrofit).
+ * Sharing a single client allows both APIs to benefit from a common connection pool, thread pool,
+ * and keep-alive settings, reducing resource consumption.
+ * If the two APIs ever require distinct timeouts or interceptors, separate clients should be created.
+ * The {@link jakarta.annotation.PreDestroy} hook ensures the client is shut down cleanly on application stop.
+ */
+ @Bean
+ public OkHttpClient okHttpClient() {
+ okHttpClient = new OkHttpClient.Builder().build();
+ return okHttpClient;
+ }
+
+ @Bean(name = "dummyUserRetrofit")
+ public Retrofit dummyUserRetrofit(OkHttpClient okHttpClient, Environment env) {
+ return new Retrofit.Builder()
+ .baseUrl(env.getRequiredProperty("dummy.api.base-url"))
+ .client(okHttpClient)
+ .addConverterFactory(GsonConverterFactory.create())
+ .build();
+ }
+
+ @Bean
+ public DummyUserApi dummyUserApi(@Qualifier("dummyUserRetrofit") Retrofit dummyUserRetrofit) {
+ return dummyUserRetrofit.create(DummyUserApi.class);
+ }
+
+ @Bean(name = "randomUserRetrofit")
+ public Retrofit randomUserRetrofit(OkHttpClient okHttpClient, Environment env) {
+ return new Retrofit.Builder()
+ .baseUrl(env.getRequiredProperty("randomuser.api.base-url"))
+ .client(okHttpClient)
+ .addConverterFactory(GsonConverterFactory.create())
+ .build();
+ }
+
+ @Bean
+ public RandomUserApi randomUserApi(@Qualifier("randomUserRetrofit") Retrofit randomUserRetrofit) {
+ return randomUserRetrofit.create(RandomUserApi.class);
+ }
+
+ @PreDestroy
+ public void destroy() {
+ if (okHttpClient != null) {
+ okHttpClient.dispatcher().executorService().shutdown();
+ okHttpClient.connectionPool().evictAll();
+ }
+ }
+}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/dummy/DummyUserApiConfig.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/dummy/DummyUserApiConfig.java
deleted file mode 100644
index 9b1dfa5..0000000
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/dummy/DummyUserApiConfig.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.xpeho.spring_boot_java_random_user.data.sources.api.dummy;
-
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.Environment;
-import retrofit2.Retrofit;
-import retrofit2.converter.gson.GsonConverterFactory;
-
-@Configuration
-public class DummyUserApiConfig {
- @Bean(name = "dummyUserRetrofit")
- public Retrofit dummyUserRetrofit(Environment env) {
- return new Retrofit.Builder()
- .baseUrl(env.getRequiredProperty("dummy.api.base-url"))
- .addConverterFactory(GsonConverterFactory.create())
- .build();
- }
-
- @Bean
- public DummyUserApi dummyUserApi(@Qualifier("dummyUserRetrofit") Retrofit dummyUserRetrofit) {
- return dummyUserRetrofit.create(DummyUserApi.class);
- }
-}
-
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/dummy/DummyUserServiceImpl.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/dummy/DummyUserServiceImpl.java
index a81423e..b250351 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/dummy/DummyUserServiceImpl.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/dummy/DummyUserServiceImpl.java
@@ -6,7 +6,7 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.PaginatedUsers;
import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
-import com.xpeho.spring_boot_java_random_user.domain.services.RemoteUserService;
+import com.xpeho.spring_boot_java_random_user.data.sources.api.RemoteUserService;
import org.springframework.stereotype.Service;
import retrofit2.Response;
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/randomuser/RandomUserApiConfig.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/randomuser/RandomUserApiConfig.java
deleted file mode 100644
index 882f3ff..0000000
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/randomuser/RandomUserApiConfig.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.xpeho.spring_boot_java_random_user.data.sources.api.randomuser;
-
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.Environment;
-import retrofit2.Retrofit;
-import retrofit2.converter.gson.GsonConverterFactory;
-
-@Configuration
-public class RandomUserApiConfig {
- @Bean(name = "randomUserRetrofit")
- public Retrofit randomUserRetrofit(Environment env) {
- return new Retrofit.Builder()
- .baseUrl(env.getRequiredProperty("randomuser.api.base-url"))
- .addConverterFactory(GsonConverterFactory.create())
- .build();
- }
-
- @Bean
- public RandomUserApi randomUserApi(@Qualifier("randomUserRetrofit") Retrofit randomUserRetrofit) {
- return randomUserRetrofit.create(RandomUserApi.class);
- }
-}
-
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/randomuser/RandomUserServiceImpl.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/randomuser/RandomUserServiceImpl.java
index b327df9..463a62f 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/randomuser/RandomUserServiceImpl.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/api/randomuser/RandomUserServiceImpl.java
@@ -6,7 +6,7 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.PaginatedUsers;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
-import com.xpeho.spring_boot_java_random_user.domain.services.RemoteUserService;
+import com.xpeho.spring_boot_java_random_user.data.sources.api.RemoteUserService;
import org.springframework.stereotype.Service;
import retrofit2.Response;
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserRepository.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserRepository.java
index b23c856..fffc289 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserRepository.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserRepository.java
@@ -1,8 +1,8 @@
package com.xpeho.spring_boot_java_random_user.data.sources.database;
-import com.xpeho.spring_boot_java_random_user.data.models.database.User;
+import com.xpeho.spring_boot_java_random_user.data.models.database.UserDAO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-public interface UserRepository extends JpaRepository, JpaSpecificationExecutor {
+public interface UserRepository extends JpaRepository, JpaSpecificationExecutor {
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserSpecifications.java b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserSpecifications.java
index f4be154..f5bb1d0 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserSpecifications.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserSpecifications.java
@@ -1,6 +1,6 @@
package com.xpeho.spring_boot_java_random_user.data.sources.database;
-import com.xpeho.spring_boot_java_random_user.data.models.database.User;
+import com.xpeho.spring_boot_java_random_user.data.models.database.UserDAO;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.Path;
@@ -15,7 +15,7 @@ public final class UserSpecifications {
private UserSpecifications() {
}
- public static Specification byFilter(UserFilter filter) {
+ public static Specification byFilter(UserFilter filter) {
return (user, query, criteriaBuilder) -> {
List predicates = new ArrayList<>();
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/exceptions/UserNotFoundException.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/exceptions/UserNotFoundException.java
index e53e627..bdf9f53 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/exceptions/UserNotFoundException.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/exceptions/UserNotFoundException.java
@@ -2,6 +2,6 @@
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(long id) {
- super("User not found with id: " + id);
+ super("UserDAO not found with id: " + id);
}
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/services/LocalUserService.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/services/LocalUserService.java
deleted file mode 100644
index 8bb472e..0000000
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/services/LocalUserService.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.xpeho.spring_boot_java_random_user.domain.services;
-
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
-
-import java.util.List;
-import java.util.Optional;
-
-public interface LocalUserService {
- List saveAll(List users);
-
- Optional getById(long id);
-
- UserEntity save(UserEntity user);
-
- void deleteById(long id);
-
- List filterUsers(UserFilter filter);
-}
-
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/services/UserService.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/services/UserService.java
new file mode 100644
index 0000000..a2a3c1f
--- /dev/null
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/services/UserService.java
@@ -0,0 +1,28 @@
+package com.xpeho.spring_boot_java_random_user.domain.services;
+
+import com.xpeho.spring_boot_java_random_user.domain.entities.PaginatedUsers;
+import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
+import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
+import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+
+public interface UserService {
+
+ List saveAll(List users);
+
+ Optional getById(long id);
+
+ UserEntity save(UserEntity user);
+
+ void deleteById(long id);
+
+ Page filterUsers(UserFilter filter, Pageable pageable);
+
+ PaginatedUsers fetchAndSaveUsers(int page, int size, UserSource source) throws IOException;
+}
+
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCase.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCase.java
index eada9af..79683b0 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCase.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCase.java
@@ -1,19 +1,18 @@
package com.xpeho.spring_boot_java_random_user.domain.usecases;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.springframework.stereotype.Service;
@Service
public class CreateUserUseCase {
- private final LocalUserService userService;
+ private final UserService userService;
- public CreateUserUseCase(LocalUserService userService) {
+ public CreateUserUseCase(UserService userService) {
this.userService = userService;
}
- public UserEntity execute(UserRequest user) {
+ public UserEntity execute(UserEntity user) {
UserEntity userToCreate = new UserEntity(
null,
user.gender(),
@@ -25,7 +24,6 @@ public UserEntity execute(UserRequest user) {
user.picture(),
user.nat()
);
-
return userService.save(userToCreate);
}
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserByIdUseCase.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserByIdUseCase.java
index e120db4..c6bbbf8 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserByIdUseCase.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserByIdUseCase.java
@@ -1,13 +1,13 @@
package com.xpeho.spring_boot_java_random_user.domain.usecases;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.springframework.stereotype.Service;
@Service
public class DeleteUserByIdUseCase {
- private final LocalUserService userService;
+ private final UserService userService;
- public DeleteUserByIdUseCase(LocalUserService userService) {
+ public DeleteUserByIdUseCase(UserService userService) {
this.userService = userService;
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FetchAndSaveRandomUsersUseCase.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FetchAndSaveRandomUsersUseCase.java
index 231dd98..1922301 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FetchAndSaveRandomUsersUseCase.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FetchAndSaveRandomUsersUseCase.java
@@ -2,35 +2,21 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.PaginatedUsers;
import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
-import com.xpeho.spring_boot_java_random_user.domain.services.RemoteUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.springframework.stereotype.Service;
import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
@Service
public class FetchAndSaveRandomUsersUseCase {
- private final LocalUserService localUserService;
- private final Map remoteUserServices;
+ private final UserService userService;
- public FetchAndSaveRandomUsersUseCase(LocalUserService localUserService, List remoteUserServices) {
- this.localUserService = localUserService;
- this.remoteUserServices = remoteUserServices.stream()
- .collect(Collectors.toMap(RemoteUserService::getSource, Function.identity()));
+ public FetchAndSaveRandomUsersUseCase(UserService userService) {
+ this.userService = userService;
}
public PaginatedUsers execute(int page, int size, UserSource source) throws IOException {
- RemoteUserService remoteUserService = remoteUserServices.get(source);
- if (remoteUserService == null) {
- throw new IllegalStateException("No remote service configured for source: " + source);
- }
- PaginatedUsers response = remoteUserService.fetchUsers(page, size);
- localUserService.saveAll(response.data());
- return response;
+ return userService.fetchAndSaveUsers(page, size, source);
}
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FilterUsersUseCase.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FilterUsersUseCase.java
index a28a71d..4a6c40c 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FilterUsersUseCase.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FilterUsersUseCase.java
@@ -2,20 +2,20 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
-import java.util.List;
-
@Service
public class FilterUsersUseCase {
- private final LocalUserService userService;
+ private final UserService userService;
- public FilterUsersUseCase(LocalUserService userService) {
+ public FilterUsersUseCase(UserService userService) {
this.userService = userService;
}
- public List execute(UserFilter filter) {
- return userService.filterUsers(filter);
+ public Page execute(UserFilter filter, Pageable pageable) {
+ return userService.filterUsers(filter, pageable);
}
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserByIdUseCase.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserByIdUseCase.java
index 730b3e4..c95ea00 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserByIdUseCase.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserByIdUseCase.java
@@ -2,14 +2,14 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.exceptions.UserNotFoundException;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.springframework.stereotype.Service;
@Service
public class GetUserByIdUseCase {
- private final LocalUserService userService;
+ private final UserService userService;
- public GetUserByIdUseCase(LocalUserService userService) {
+ public GetUserByIdUseCase(UserService userService) {
this.userService = userService;
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserUseCase.java b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserUseCase.java
index 5a17aad..17e9523 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserUseCase.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserUseCase.java
@@ -1,33 +1,32 @@
package com.xpeho.spring_boot_java_random_user.domain.usecases;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest;
import com.xpeho.spring_boot_java_random_user.domain.exceptions.UserNotFoundException;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.springframework.stereotype.Service;
@Service
public class UpdateRandomUserUseCase {
- private final LocalUserService userService;
+ private final UserService userService;
- public UpdateRandomUserUseCase(LocalUserService userService) {
+ public UpdateRandomUserUseCase(UserService userService) {
this.userService = userService;
}
- public UserEntity execute(int id, UserRequest user) {
+ public UserEntity execute(long id, UserEntity newData) {
UserEntity existingUser = userService.getById(id)
.orElseThrow(() -> new UserNotFoundException(id));
UserEntity updatedUser = new UserEntity(
existingUser.id(),
- user.gender(),
- user.firstname(),
- user.lastname(),
- user.civility(),
- user.email(),
- user.phone(),
- user.picture(),
- user.nat()
+ newData.gender(),
+ newData.firstname(),
+ newData.lastname(),
+ newData.civility(),
+ newData.email(),
+ newData.phone(),
+ newData.picture(),
+ newData.nat()
);
return userService.save(updatedUser);
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/controllers/UserController.java b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/controllers/UserController.java
index abe1376..bd129e9 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/controllers/UserController.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/controllers/UserController.java
@@ -1,9 +1,9 @@
package com.xpeho.spring_boot_java_random_user.presentation.controllers;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest;
import com.xpeho.spring_boot_java_random_user.domain.enums.Gender;
import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
+import com.xpeho.spring_boot_java_random_user.presentation.dto.UserRequest;
import com.xpeho.spring_boot_java_random_user.presentation.dto.UserResponseDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -11,15 +11,13 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
+import org.springframework.data.domain.Page;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
-import java.util.List;
-
-
@RequestMapping("/random-users")
-@Tag(name = "User", description = "Endpoints for random user generation")
+@Tag(name = "UserDAO", description = "Endpoints for random user generation")
public interface UserController {
@GetMapping("")
@@ -55,7 +53,7 @@ ResponseEntity getRandomUsers(
@Parameter(name = "id", description = "id of the requested user")
}
)
- @ApiResponse(responseCode = "200", description = "User successfully found and returned")
+ @ApiResponse(responseCode = "200", description = "UserDAO successfully found and returned")
@ApiResponse(responseCode = "404", description = "The requested user does not exist")
@ApiResponse(responseCode = "500", description = "Internal server error")
ResponseEntity getUserById(
@@ -69,10 +67,10 @@ ResponseEntity getUserById(
description = "Giving a random user id, modify the content of the user",
parameters = {
@Parameter(name = "id", description = "id of the requested user"),
- @Parameter(name = "UserEntity", description = "changeable parameters")
+ @Parameter(name = "UserRequest", description = "changeable parameters")
}
)
- @ApiResponse(responseCode = "200", description = "User successfully modified and saved")
+ @ApiResponse(responseCode = "200", description = "UserDAO successfully modified and saved")
@ApiResponse(responseCode = "404", description = "The requested user does not exist")
@ApiResponse(responseCode = "500", description = "Internal server error")
ResponseEntity updateRandomUser(
@@ -87,10 +85,10 @@ ResponseEntity updateRandomUser(
summary = "Create a user",
description = "Creates a new user in the database.",
parameters = {
- @Parameter(name = "UserRequest", description = "User data to persist")
+ @Parameter(name = "UserRequest", description = "UserDAO data to persist")
}
)
- @ApiResponse(responseCode = "201", description = "User successfully created")
+ @ApiResponse(responseCode = "201", description = "UserDAO successfully created")
@ApiResponse(responseCode = "500", description = "Internal server error")
ResponseEntity createUser(@RequestBody UserRequest user);
@@ -98,7 +96,7 @@ ResponseEntity updateRandomUser(
@GetMapping("/filter")
@Operation(
summary = "Filter users",
- description = "Search users by optional filters on gender, firstname, lastname, civility, email, phone and nationality. All filters are case-insensitive and support partial matching.",
+ description = "Search users by optional filters on gender, firstname, lastname, civility, email, phone and nationality. All filters are case-insensitive and support partial matching. Supports pagination via page and size parameters.",
parameters = {
@Parameter(name = "gender", description = "Filter by gender (MALE or FEMALE)"),
@Parameter(name = "firstname", description = "Filter by firstname"),
@@ -106,19 +104,23 @@ ResponseEntity updateRandomUser(
@Parameter(name = "civility", description = "Filter by civility"),
@Parameter(name = "email", description = "Filter by email"),
@Parameter(name = "phone", description = "Filter by phone"),
- @Parameter(name = "nat", description = "Filter by nationality")
+ @Parameter(name = "nat", description = "Filter by nationality"),
+ @Parameter(name = "page", description = "Page index (0-based)", example = "0"),
+ @Parameter(name = "size", description = "Page size", example = "20")
}
)
- @ApiResponse(responseCode = "200", description = "Filtered list of users")
+ @ApiResponse(responseCode = "200", description = "Paginated filtered list of users")
@ApiResponse(responseCode = "500", description = "Internal server error")
- ResponseEntity> filterUsers(
+ ResponseEntity> filterUsers(
@RequestParam(required = false) Gender gender,
@RequestParam(required = false) String firstname,
@RequestParam(required = false) String lastname,
@RequestParam(required = false) String civility,
@RequestParam(required = false) String email,
@RequestParam(required = false) String phone,
- @RequestParam(required = false) String nat
+ @RequestParam(required = false) String nat,
+ @RequestParam(defaultValue = "0") int page,
+ @RequestParam(defaultValue = "20") int size
);
@DeleteMapping("/{id}")
@@ -129,7 +131,7 @@ ResponseEntity> filterUsers(
@Parameter(name = "id", description = "id of the requested user")
}
)
- @ApiResponse(responseCode = "204", description = "User successfully deleted")
+ @ApiResponse(responseCode = "204", description = "UserDAO successfully deleted")
@ApiResponse(responseCode = "404", description = "The requested user does not exist")
@ApiResponse(responseCode = "500", description = "Internal server error")
void deleteUserById(
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/dto/PaginatedRequest.java b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/dto/PaginatedRequest.java
new file mode 100644
index 0000000..a1cd851
--- /dev/null
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/dto/PaginatedRequest.java
@@ -0,0 +1,11 @@
+package com.xpeho.spring_boot_java_random_user.presentation.dto;
+
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+
+public record PaginatedRequest(int page, int size) {
+ public Pageable toPageable() {
+ return PageRequest.of(page, size);
+ }
+}
+
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/entities/UserRequest.java b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/dto/UserRequest.java
similarity index 76%
rename from src/main/java/com/xpeho/spring_boot_java_random_user/domain/entities/UserRequest.java
rename to src/main/java/com/xpeho/spring_boot_java_random_user/presentation/dto/UserRequest.java
index a923b54..5136d54 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/domain/entities/UserRequest.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/dto/UserRequest.java
@@ -1,4 +1,4 @@
-package com.xpeho.spring_boot_java_random_user.domain.entities;
+package com.xpeho.spring_boot_java_random_user.presentation.dto;
public record UserRequest(
String gender,
@@ -11,3 +11,4 @@ public record UserRequest(
String nat
) {
}
+
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/exceptions/GlobalExceptionHandler.java b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/exceptions/GlobalExceptionHandler.java
index 2429896..92d3f45 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/exceptions/GlobalExceptionHandler.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/exceptions/GlobalExceptionHandler.java
@@ -40,7 +40,7 @@ public ResponseEntity handleMethodArgumentTypeMismatch(MethodArgu
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity handleUserNotFoundException(UserNotFoundException ex) {
- logger.warn("User not found: {}", ex.getMessage());
+ logger.warn("UserDAO not found: {}", ex.getMessage());
return buildErrorResponse("USER_NOT_FOUND", ex.getMessage(), HttpStatus.NOT_FOUND);
}
diff --git a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/handlers/UserHandler.java b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/handlers/UserHandler.java
index c6d81c2..9959b71 100644
--- a/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/handlers/UserHandler.java
+++ b/src/main/java/com/xpeho/spring_boot_java_random_user/presentation/handlers/UserHandler.java
@@ -3,15 +3,17 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.PaginatedUsers;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest;
import com.xpeho.spring_boot_java_random_user.domain.enums.Gender;
import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
import com.xpeho.spring_boot_java_random_user.domain.exceptions.UserNotFoundException;
import com.xpeho.spring_boot_java_random_user.domain.usecases.*;
import com.xpeho.spring_boot_java_random_user.presentation.controllers.UserController;
+import com.xpeho.spring_boot_java_random_user.presentation.dto.PaginatedRequest;
+import com.xpeho.spring_boot_java_random_user.presentation.dto.UserRequest;
import com.xpeho.spring_boot_java_random_user.presentation.dto.UserResponseDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
@@ -19,7 +21,6 @@
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
-import java.util.List;
@Validated
@@ -73,7 +74,8 @@ public ResponseEntity getRandomUsers(int page, int size, UserSo
@Override
public ResponseEntity updateRandomUser(int id, UserRequest user) {
try {
- UserEntity savedUser = updateRandomUserUseCase.execute(id, user);
+ UserEntity userEntity = toEntity(user);
+ UserEntity savedUser = updateRandomUserUseCase.execute(id, userEntity);
return ResponseEntity.ok(savedUser);
} catch (UserNotFoundException e) {
logUserNotFound(e);
@@ -95,17 +97,20 @@ public ResponseEntity getUserById(int id) {
@Override
public ResponseEntity createUser(@RequestBody UserRequest user) {
- UserEntity createdUser = createUserUseCase.execute(user);
+ UserEntity userEntity = toEntity(user);
+ UserEntity createdUser = createUserUseCase.execute(userEntity);
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}
@Override
- public ResponseEntity> filterUsers(
+ public ResponseEntity> filterUsers(
Gender gender, String firstname, String lastname,
- String civility, String email, String phone, String nat
+ String civility, String email, String phone, String nat,
+ int page, int size
) {
UserFilter filter = new UserFilter(gender, firstname, lastname, civility, email, phone, nat);
- List users = filterUsersUseCase.execute(filter);
+ PaginatedRequest pagination = new PaginatedRequest(page, size);
+ Page users = filterUsersUseCase.execute(filter, pagination.toPageable());
return ResponseEntity.ok(users);
}
@@ -118,6 +123,20 @@ public void deleteUserById(int id) {
}
}
+ private UserEntity toEntity(UserRequest user) {
+ return new UserEntity(
+ null,
+ user.gender(),
+ user.firstname(),
+ user.lastname(),
+ user.civility(),
+ user.email(),
+ user.phone(),
+ user.picture(),
+ user.nat()
+ );
+ }
+
private void logUserNotFound(UserNotFoundException e) {
logger.warn(USER_NOT_FOUND_LOG, e.getMessage());
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 62f00f1..464b1ac 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -3,8 +3,8 @@ spring.application.name=spring_boot_java_random_user
# Security
app.security.admin.username=${APP_SECURITY_ADMIN_USER}
app.security.admin.password=${APP_SECURITY_ADMIN_PASSWORD}
-app.security.user.username=${APP_SECURITY_USER}
-app.security.user.password=${APP_SECURITY_PASSWORD}
+app.security.userDAO.username=${APP_SECURITY_USER}
+app.security.userDAO.password=${APP_SECURITY_PASSWORD}
app.security.test.username=${APP_SECURITY_TEST_USER}
app.security.test.password=${APP_SECURITY_TEST_PASSWORD}
@@ -14,7 +14,7 @@ springdoc.swagger-ui.path=/api
# URL for Dummy API
dummy.api.base-url=https://dummyjson.com/
-# URL for random user API
+# URL for random userDAO API
randomuser.api.base-url=https://randomuser.me/api/
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/SpringBootJavaRandomUserApplicationTests.java b/src/test/java/com/xpeho/spring_boot_java_random_user/SpringBootJavaRandomUserDAOApplicationTests.java
similarity index 94%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/SpringBootJavaRandomUserApplicationTests.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/SpringBootJavaRandomUserDAOApplicationTests.java
index 073dbe8..c37da02 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/SpringBootJavaRandomUserApplicationTests.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/SpringBootJavaRandomUserDAOApplicationTests.java
@@ -13,7 +13,7 @@
@SpringBootTest
@ActiveProfiles("test")
-class SpringBootJavaRandomUserApplicationTests {
+class SpringBootJavaRandomUserDAOApplicationTests {
@Autowired
ApplicationContext applicationContext;
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/converters/UserConverterTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/converters/UserDAOConverterTest.java
similarity index 98%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/converters/UserConverterTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/converters/UserDAOConverterTest.java
index 8e97b5c..21c0b76 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/converters/UserConverterTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/converters/UserDAOConverterTest.java
@@ -4,14 +4,14 @@
import com.xpeho.spring_boot_java_random_user.data.models.api.randomuser.RandomUserNameDTO;
import com.xpeho.spring_boot_java_random_user.data.models.api.randomuser.RandomUserPictureDTO;
import com.xpeho.spring_boot_java_random_user.data.models.api.randomuser.RandomUserResultDTO;
+import com.xpeho.spring_boot_java_random_user.data.models.database.UserDAO;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
-import com.xpeho.spring_boot_java_random_user.data.models.database.User;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
-class UserConverterTest {
+class UserDAOConverterTest {
private final UserConverter converter = new UserConverter();
@Test
@@ -104,7 +104,7 @@ void shouldHandleMissingNestedFieldsFromRandomUserApiModel() {
@DisplayName("Should convert domain to DB and back without losing data")
void shouldConvertDomainToDbAndBackWithoutLosingData() {
UserEntity entity = new UserEntity(1L, "male", "John", "Doe", "Mr", "john@doe.com", "1234", "pic.jpg", "FR");
- User dao = converter.toDao(entity);
+ UserDAO dao = converter.toDao(entity);
assertEquals(entity.id(), dao.getId());
assertEquals(entity.firstname(), dao.getFirstname());
assertEquals(entity.lastname(), dao.getLastname());
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserResponseTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserDAOResponseTest.java
similarity index 96%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserResponseTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserDAOResponseTest.java
index 3eda125..616e208 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserResponseTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserDAOResponseTest.java
@@ -5,7 +5,7 @@
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
-class DummyUserResponseTest {
+class DummyUserDAOResponseTest {
@Test
@DisplayName("Should store and return users list")
void shouldStoreAndReturnUsersList() {
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserResultDTOTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserDTOResultDAOTest.java
similarity index 97%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserResultDTOTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserDTOResultDAOTest.java
index a4eff1d..bb8b8e9 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserResultDTOTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/dummy/DummyUserDTOResultDAOTest.java
@@ -4,7 +4,7 @@
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
-class DummyUserResultDTOTest {
+class DummyUserDTOResultDAOTest {
@Test
@DisplayName("Should store and return all user fields")
void shouldStoreAndReturnAllUserFields() {
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserNameDTOTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTONameDAOTest.java
similarity index 96%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserNameDTOTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTONameDAOTest.java
index 8ae05d8..d21c936 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserNameDTOTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTONameDAOTest.java
@@ -6,7 +6,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
-class RandomUserNameDTOTest {
+class RandomUserDTONameDAOTest {
@Test
@DisplayName("Should store and return all name fields")
void shouldStoreAndReturnAllNameFields() {
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserPictureDTOTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTOPictureDAOTest.java
similarity index 95%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserPictureDTOTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTOPictureDAOTest.java
index 6c47d24..0800f82 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserPictureDTOTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTOPictureDAOTest.java
@@ -6,7 +6,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
-class RandomUserPictureDTOTest {
+class RandomUserDTOPictureDAOTest {
@Test
@DisplayName("Should store and return medium picture URL")
void shouldStoreAndReturnMediumPictureUrl() {
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserResponseDTOTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTOResponseDAOTest.java
similarity index 96%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserResponseDTOTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTOResponseDAOTest.java
index 0cb1af7..60f9880 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserResponseDTOTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTOResponseDAOTest.java
@@ -8,7 +8,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
-class RandomUserResponseDTOTest {
+class RandomUserDTOResponseDAOTest {
@Test
@DisplayName("Should store and return results list")
void shouldStoreAndReturnResultsList() {
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserResultDTOTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTOResultDAOTest.java
similarity index 97%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserResultDTOTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTOResultDAOTest.java
index fee3333..509f61c 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserResultDTOTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/models/api/randomuser/RandomUserDTOResultDAOTest.java
@@ -6,7 +6,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
-class RandomUserResultDTOTest {
+class RandomUserDTOResultDAOTest {
@Test
@DisplayName("Should store and return all user fields")
void shouldStoreAndReturnAllUserFields() {
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImplTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserDAOServiceImplTest.java
similarity index 69%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImplTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserDAOServiceImplTest.java
index 942d99e..d8a0f10 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserServiceImplTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/services/UserDAOServiceImplTest.java
@@ -1,7 +1,7 @@
package com.xpeho.spring_boot_java_random_user.data.services;
import com.xpeho.spring_boot_java_random_user.data.converters.UserConverter;
-import com.xpeho.spring_boot_java_random_user.data.models.database.User;
+import com.xpeho.spring_boot_java_random_user.data.models.database.UserDAO;
import com.xpeho.spring_boot_java_random_user.data.sources.database.UserRepository;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
@@ -9,6 +9,10 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import java.util.Collections;
@@ -17,11 +21,13 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-class UserServiceImplTest {
+class UserDAOServiceImplTest {
private UserRepository userRepository;
private UserConverter userConverter;
private UserServiceImpl userService;
@@ -30,13 +36,13 @@ class UserServiceImplTest {
void setUp() {
userRepository = mock(UserRepository.class);
userConverter = mock(UserConverter.class);
- userService = new UserServiceImpl(userRepository, userConverter);
+ userService = new UserServiceImpl(userRepository, userConverter, List.of());
}
@Test
@DisplayName("Should return mapped user when id exists")
void shouldReturnMappedUserWhenIdExists() {
- User dao = new User();
+ UserDAO dao = new UserDAO();
dao.setId(1L);
dao.setFirstname("John");
@@ -69,10 +75,10 @@ void shouldReturnEmptyOptionalWhenIdDoesNotExist() {
void shouldSaveMappedUserAndReturnMappedDomainEntity() {
UserEntity input = new UserEntity(3L, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US");
- User daoToSave = new User();
+ UserDAO daoToSave = new UserDAO();
daoToSave.setFirstname("Alice");
- User savedDao = new User();
+ UserDAO savedDao = new UserDAO();
savedDao.setId(3L);
savedDao.setFirstname("Alice");
@@ -94,22 +100,23 @@ void shouldSaveMappedUserAndReturnMappedDomainEntity() {
@DisplayName("Should build a specification and call repository for filtered users")
void shouldFilterUsersWithGender() {
UserFilter filter = new UserFilter(Gender.MALE, "John", null, null, null, null, null);
+ Pageable pageable = PageRequest.of(0, 20);
- User dao = new User();
+ UserDAO dao = new UserDAO();
dao.setId(1L);
dao.setFirstname("John");
UserEntity expected = new UserEntity(1L, "male", "John", "Doe", "Mr", "john@doe.com", "1234", "pic.jpg", "FR");
+ Page daoPage = new PageImpl<>(List.of(dao), pageable, 1);
- when(userRepository.findAll(org.mockito.ArgumentMatchers.>any()))
- .thenReturn(List.of(dao));
+ when(userRepository.findAll(any(Specification.class), eq(pageable))).thenReturn(daoPage);
when(userConverter.toDomain(dao)).thenReturn(expected);
- List result = userService.filterUsers(filter);
+ Page result = userService.filterUsers(filter, pageable);
- assertEquals(1, result.size());
- assertEquals(expected, result.get(0));
- verify(userRepository).findAll(org.mockito.ArgumentMatchers.>any());
+ assertEquals(1, result.getTotalElements());
+ assertEquals(expected, result.getContent().get(0));
+ verify(userRepository).findAll(any(Specification.class), eq(pageable));
verify(userConverter).toDomain(dao);
}
@@ -117,35 +124,37 @@ void shouldFilterUsersWithGender() {
@DisplayName("Should call repository when gender filter is null")
void shouldFilterUsersWithNullGender() {
UserFilter filter = new UserFilter(null, null, "Smith", null, null, null, null);
+ Pageable pageable = PageRequest.of(0, 20);
- User dao = new User();
+ UserDAO dao = new UserDAO();
dao.setId(2L);
dao.setLastname("Smith");
UserEntity expected = new UserEntity(2L, "female", "Alice", "Smith", "Ms", "alice@smith.com", "5678", "pic2.jpg", "US");
+ Page daoPage = new PageImpl<>(List.of(dao), pageable, 1);
- when(userRepository.findAll(org.mockito.ArgumentMatchers.>any()))
- .thenReturn(List.of(dao));
+ when(userRepository.findAll(any(Specification.class), eq(pageable))).thenReturn(daoPage);
when(userConverter.toDomain(dao)).thenReturn(expected);
- List result = userService.filterUsers(filter);
+ Page result = userService.filterUsers(filter, pageable);
- assertEquals(1, result.size());
- assertEquals(expected, result.get(0));
- verify(userRepository).findAll(org.mockito.ArgumentMatchers.>any());
+ assertEquals(1, result.getTotalElements());
+ assertEquals(expected, result.getContent().get(0));
+ verify(userRepository).findAll(any(Specification.class), eq(pageable));
}
@Test
- @DisplayName("Should return empty list when no users match filter")
+ @DisplayName("Should return empty page when no users match filter")
void shouldReturnEmptyListWhenNoUsersMatchFilter() {
UserFilter filter = new UserFilter(Gender.FEMALE, "Unknown", null, null, null, null, null);
+ Pageable pageable = PageRequest.of(0, 20);
+ Page emptyPage = new PageImpl<>(Collections.emptyList(), pageable, 0);
- when(userRepository.findAll(org.mockito.ArgumentMatchers.>any()))
- .thenReturn(Collections.emptyList());
+ when(userRepository.findAll(any(Specification.class), eq(pageable))).thenReturn(emptyPage);
- List result = userService.filterUsers(filter);
+ Page result = userService.filterUsers(filter, pageable);
assertTrue(result.isEmpty());
- verify(userRepository).findAll(org.mockito.ArgumentMatchers.>any());
+ verify(userRepository).findAll(any(Specification.class), eq(pageable));
}
}
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/DummyUserServiceImplTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/DummyUserDAOServiceImplTest.java
similarity index 99%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/DummyUserServiceImplTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/DummyUserDAOServiceImplTest.java
index bb357df..cdd4aa1 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/DummyUserServiceImplTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/DummyUserDAOServiceImplTest.java
@@ -20,7 +20,7 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
-class DummyUserServiceImplTest {
+class DummyUserDAOServiceImplTest {
private DummyUserApi dummyUserApi;
private UserConverter userConverter;
private DummyUserServiceImpl service;
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/RandomUserServiceImplTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/RandomUserDAOServiceImplTest.java
similarity index 99%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/RandomUserServiceImplTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/RandomUserDAOServiceImplTest.java
index 6f75460..c5b0053 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/RandomUserServiceImplTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/RandomUserDAOServiceImplTest.java
@@ -22,7 +22,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-class RandomUserServiceImplTest {
+class RandomUserDAOServiceImplTest {
private RandomUserApi randomUserApi;
private UserConverter userConverter;
private RandomUserServiceImpl service;
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserSpecificationsTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserDAOSpecificationsTest.java
similarity index 92%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserSpecificationsTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserDAOSpecificationsTest.java
index cbe3095..ab0d468 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserSpecificationsTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/data/sources/database/UserDAOSpecificationsTest.java
@@ -1,6 +1,6 @@
package com.xpeho.spring_boot_java_random_user.data.sources.database;
-import com.xpeho.spring_boot_java_random_user.data.models.database.User;
+import com.xpeho.spring_boot_java_random_user.data.models.database.UserDAO;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
import jakarta.persistence.criteria.*;
import org.junit.jupiter.api.BeforeEach;
@@ -10,8 +10,8 @@
import static org.mockito.Mockito.*;
-class UserSpecificationsTest {
- private Root user;
+class UserDAOSpecificationsTest {
+ private Root user;
private CriteriaQuery> query;
private CriteriaBuilder cb;
private Expression lowerExpr;
@@ -38,7 +38,7 @@ void setUp() {
void shouldAddLikePredicatesForAllTextFields() {
UserFilter filter = new UserFilter(null, "John", "Doe", "Mr", "john@doe.com", "1234", "FR");
- Specification spec = UserSpecifications.byFilter(filter);
+ Specification spec = UserSpecifications.byFilter(filter);
spec.toPredicate(user, query, cb);
verify(user).get("firstname");
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCaseTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserDAOUseCaseTest.java
similarity index 75%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCaseTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserDAOUseCaseTest.java
index 4a99dd5..8bddb24 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserUseCaseTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/CreateUserDAOUseCaseTest.java
@@ -1,8 +1,7 @@
package com.xpeho.spring_boot_java_random_user.domain.usecases;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -12,21 +11,21 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-class CreateUserUseCaseTest {
- private LocalUserService userService;
+class CreateUserDAOUseCaseTest {
+ private UserService userService;
private CreateUserUseCase useCase;
@BeforeEach
void setUp() {
- userService = mock(LocalUserService.class);
+ userService = mock(UserService.class);
useCase = new CreateUserUseCase(userService);
}
@Test
@DisplayName("Should create a user without keeping the input id")
void shouldCreateUserWithoutKeepingInputId() {
- UserRequest payload = new UserRequest(
- "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"
+ UserEntity payload = new UserEntity(
+ 99L, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"
);
UserEntity createdUser = new UserEntity(
1L, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserByIdUseCaseTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserDAOByIdUseCaseTest.java
similarity index 88%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserByIdUseCaseTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserDAOByIdUseCaseTest.java
index 73d8000..3ef8fb7 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserByIdUseCaseTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/DeleteUserDAOByIdUseCaseTest.java
@@ -1,19 +1,19 @@
package com.xpeho.spring_boot_java_random_user.domain.usecases;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
-class DeleteUserByIdUseCaseTest {
- private LocalUserService userService;
+class DeleteUserDAOByIdUseCaseTest {
+ private UserService userService;
private DeleteUserByIdUseCase useCase;
@BeforeEach
void setUp() {
- userService = mock(LocalUserService.class);
+ userService = mock(UserService.class);
useCase = new DeleteUserByIdUseCase(userService);
}
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FetchAndSaveRandomUsersUseCaseTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FetchAndSaveRandomUsersUseCaseTest.java
index 1b867da..9181630 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FetchAndSaveRandomUsersUseCaseTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FetchAndSaveRandomUsersUseCaseTest.java
@@ -3,8 +3,7 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.PaginatedUsers;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
-import com.xpeho.spring_boot_java_random_user.domain.services.RemoteUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -16,19 +15,13 @@
import static org.mockito.Mockito.*;
class FetchAndSaveRandomUsersUseCaseTest {
- private LocalUserService userService;
- private RemoteUserService dummyRemoteUserService;
- private RemoteUserService randomRemoteUserService;
+ private UserService userService;
private FetchAndSaveRandomUsersUseCase useCase;
@BeforeEach
void setUp() {
- userService = mock(LocalUserService.class);
- dummyRemoteUserService = mock(RemoteUserService.class);
- randomRemoteUserService = mock(RemoteUserService.class);
- when(dummyRemoteUserService.getSource()).thenReturn(UserSource.DUMMY);
- when(randomRemoteUserService.getSource()).thenReturn(UserSource.RANDOM_USER);
- useCase = new FetchAndSaveRandomUsersUseCase(userService, List.of(dummyRemoteUserService, randomRemoteUserService));
+ userService = mock(UserService.class);
+ useCase = new FetchAndSaveRandomUsersUseCase(userService);
}
@Test
@@ -36,25 +29,20 @@ void setUp() {
void shouldFetchUsersFromApiAndSaveThem() throws IOException {
int page = 1;
int size = 10;
- int total = 50;
- int skip = 0;
- int limit = 10;
List fetched = List.of(new UserEntity(
1L, "male", "John", "Doe", "Mr", "john@doe.com", "1234", "pic.jpg", "FR"
));
- PaginatedUsers paginatedUsers = new PaginatedUsers(fetched, total, skip, limit);
- when(dummyRemoteUserService.fetchUsers(page, size)).thenReturn(paginatedUsers);
- when(userService.saveAll(fetched)).thenReturn(fetched);
+ PaginatedUsers paginatedUsers = new PaginatedUsers(fetched, 50, 0, 10);
+ when(userService.fetchAndSaveUsers(page, size, UserSource.DUMMY)).thenReturn(paginatedUsers);
PaginatedUsers result = useCase.execute(page, size, UserSource.DUMMY);
assertEquals(paginatedUsers, result);
assertEquals(fetched, result.data());
- assertEquals(total, result.total());
- assertEquals(skip, result.skip());
- assertEquals(limit, result.limit());
- verify(dummyRemoteUserService).fetchUsers(page, size);
- verify(userService).saveAll(fetched);
+ assertEquals(50, result.total());
+ assertEquals(0, result.skip());
+ assertEquals(10, result.limit());
+ verify(userService).fetchAndSaveUsers(page, size, UserSource.DUMMY);
}
@Test
@@ -62,7 +50,8 @@ void shouldFetchUsersFromApiAndSaveThem() throws IOException {
void shouldPropagateIOExceptionWhenApiFails() throws IOException {
int page = 1;
int size = 10;
- when(randomRemoteUserService.fetchUsers(page, size)).thenThrow(new IOException("API error"));
+ when(userService.fetchAndSaveUsers(page, size, UserSource.RANDOM_USER)).thenThrow(new IOException("API error"));
+
IOException ex = assertThrows(IOException.class, () -> useCase.execute(page, size, UserSource.RANDOM_USER));
assertEquals("API error", ex.getMessage());
}
@@ -72,15 +61,13 @@ void shouldPropagateIOExceptionWhenApiFails() throws IOException {
void shouldHandleEmptyUsersListGracefully() throws IOException {
int page = 1;
int size = 10;
- int total = 0;
- PaginatedUsers paginatedUsers = new PaginatedUsers(List.of(), total, 0, 10);
- when(dummyRemoteUserService.fetchUsers(page, size)).thenReturn(paginatedUsers);
- when(userService.saveAll(List.of())).thenReturn(List.of());
+ PaginatedUsers paginatedUsers = new PaginatedUsers(List.of(), 0, 0, 10);
+ when(userService.fetchAndSaveUsers(page, size, UserSource.DUMMY)).thenReturn(paginatedUsers);
PaginatedUsers result = useCase.execute(page, size, UserSource.DUMMY);
assertEquals(paginatedUsers, result);
assertTrue(result.data().isEmpty());
- assertEquals(total, result.total());
+ assertEquals(0, result.total());
}
}
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FilterUsersUseCaseTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FilterUsersUseCaseTest.java
index 368f69f..1470e54 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FilterUsersUseCaseTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/FilterUsersUseCaseTest.java
@@ -3,10 +3,14 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
import com.xpeho.spring_boot_java_random_user.domain.enums.Gender;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
import java.util.Collections;
import java.util.List;
@@ -15,55 +19,60 @@
import static org.mockito.Mockito.*;
class FilterUsersUseCaseTest {
- private LocalUserService userService;
+ private UserService userService;
private FilterUsersUseCase useCase;
+ private Pageable pageable;
@BeforeEach
void setUp() {
- userService = mock(LocalUserService.class);
+ userService = mock(UserService.class);
useCase = new FilterUsersUseCase(userService);
+ pageable = PageRequest.of(0, 20);
}
@Test
@DisplayName("Should return filtered users matching the filter")
void shouldReturnFilteredUsers() {
UserFilter filter = new UserFilter(Gender.MALE, "John", null, null, null, null, null);
- List expected = List.of(
+ List content = List.of(
new UserEntity(1L, "male", "John", "Doe", "Mr", "john@example.com", "0600000000", "http://pic.jpg", "FR")
);
- when(userService.filterUsers(filter)).thenReturn(expected);
+ Page expected = new PageImpl<>(content, pageable, 1);
+ when(userService.filterUsers(filter, pageable)).thenReturn(expected);
- List result = useCase.execute(filter);
+ Page result = useCase.execute(filter, pageable);
assertEquals(expected, result);
- verify(userService).filterUsers(filter);
+ verify(userService).filterUsers(filter, pageable);
}
@Test
- @DisplayName("Should return empty list when no users match the filter")
+ @DisplayName("Should return empty page when no users match the filter")
void shouldReturnEmptyListWhenNoMatch() {
UserFilter filter = new UserFilter(Gender.FEMALE, "Unknown", null, null, null, null, null);
- when(userService.filterUsers(filter)).thenReturn(Collections.emptyList());
+ Page empty = new PageImpl<>(Collections.emptyList(), pageable, 0);
+ when(userService.filterUsers(filter, pageable)).thenReturn(empty);
- List result = useCase.execute(filter);
+ Page result = useCase.execute(filter, pageable);
assertTrue(result.isEmpty());
- verify(userService).filterUsers(filter);
+ verify(userService).filterUsers(filter, pageable);
}
@Test
@DisplayName("Should pass filter with all fields to the service")
void shouldPassFilterWithAllFields() {
UserFilter filter = new UserFilter(Gender.FEMALE, "Alice", "Smith", "Ms", "alice@example.com", "0611111111", "US");
- List expected = List.of(
+ List content = List.of(
new UserEntity(5L, "female", "Alice", "Smith", "Ms", "alice@example.com", "0611111111", "http://pic2.jpg", "US")
);
- when(userService.filterUsers(filter)).thenReturn(expected);
+ Page expected = new PageImpl<>(content, pageable, 1);
+ when(userService.filterUsers(filter, pageable)).thenReturn(expected);
- List result = useCase.execute(filter);
+ Page result = useCase.execute(filter, pageable);
assertEquals(expected, result);
- verify(userService, times(1)).filterUsers(filter);
+ verify(userService, times(1)).filterUsers(filter, pageable);
verifyNoMoreInteractions(userService);
}
}
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserByIdUseCaseTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserDAOByIdUseCaseTest.java
similarity index 92%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserByIdUseCaseTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserDAOByIdUseCaseTest.java
index cbbf0c1..854ee42 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserByIdUseCaseTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/GetUserDAOByIdUseCaseTest.java
@@ -2,7 +2,7 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.exceptions.UserNotFoundException;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -12,13 +12,13 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
-class GetUserByIdUseCaseTest {
- private LocalUserService userService;
+class GetUserDAOByIdUseCaseTest {
+ private UserService userService;
private GetUserByIdUseCase useCase;
@BeforeEach
void setUp() {
- userService = mock(LocalUserService.class);
+ userService = mock(UserService.class);
useCase = new GetUserByIdUseCase(userService);
}
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserUseCaseTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserDAOUseCaseTest.java
similarity index 75%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserUseCaseTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserDAOUseCaseTest.java
index 1d8a5a8..bd1d776 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserUseCaseTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/domain/usecases/UpdateRandomUserDAOUseCaseTest.java
@@ -1,9 +1,8 @@
package com.xpeho.spring_boot_java_random_user.domain.usecases;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest;
import com.xpeho.spring_boot_java_random_user.domain.exceptions.UserNotFoundException;
-import com.xpeho.spring_boot_java_random_user.domain.services.LocalUserService;
+import com.xpeho.spring_boot_java_random_user.domain.services.UserService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -18,13 +17,13 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-class UpdateRandomUserUseCaseTest {
- private LocalUserService userService;
+class UpdateRandomUserDAOUseCaseTest {
+ private UserService userService;
private UpdateRandomUserUseCase useCase;
@BeforeEach
void setUp() {
- userService = mock(LocalUserService.class);
+ userService = mock(UserService.class);
useCase = new UpdateRandomUserUseCase(userService);
}
@@ -34,8 +33,8 @@ void shouldUpdateExistingUserAndPreserveItsId() {
UserEntity existingUser = new UserEntity(
42L, "male", "John", "Doe", "Mr", "john@doe.com", "1234", "pic.jpg", "FR"
);
- UserRequest request = new UserRequest(
- "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"
+ UserEntity newData = new UserEntity(
+ null, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"
);
UserEntity savedUser = new UserEntity(
42L, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"
@@ -46,7 +45,7 @@ void shouldUpdateExistingUserAndPreserveItsId() {
42L, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"
))).thenReturn(savedUser);
- UserEntity result = useCase.execute(42, request);
+ UserEntity result = useCase.execute(42, newData);
assertEquals(savedUser, result);
verify(userService).getById(42);
@@ -58,18 +57,18 @@ void shouldUpdateExistingUserAndPreserveItsId() {
@Test
@DisplayName("Should throw when updating a user that does not exist")
void shouldThrowWhenUserDoesNotExist() {
- UserRequest request = new UserRequest(
- "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"
+ UserEntity newData = new UserEntity(
+ null, "female", "Alice", "Smith", "Mrs", "alice@smith.com", "5678", "new-pic.jpg", "US"
);
when(userService.getById(99)).thenReturn(Optional.empty());
UserNotFoundException exception = assertThrows(
UserNotFoundException.class,
- () -> useCase.execute(99, request)
+ () -> useCase.execute(99, newData)
);
- assertEquals("User not found with id: 99", exception.getMessage());
+ assertEquals("UserDAO not found with id: 99", exception.getMessage());
verify(userService).getById(99);
verify(userService, never()).save(any(UserEntity.class));
}
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserGetByIdContainerTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserDAOGetByIdContainerTest.java
similarity index 87%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserGetByIdContainerTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserDAOGetByIdContainerTest.java
index 1468bd9..a4e927a 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserGetByIdContainerTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserDAOGetByIdContainerTest.java
@@ -1,6 +1,6 @@
package com.xpeho.spring_boot_java_random_user.presentation;
-import com.xpeho.spring_boot_java_random_user.data.models.database.User;
+import com.xpeho.spring_boot_java_random_user.data.models.database.UserDAO;
import com.xpeho.spring_boot_java_random_user.data.sources.database.UserRepository;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import org.junit.jupiter.api.BeforeEach;
@@ -37,7 +37,7 @@
"logging.level.com.zaxxer.hikari.pool.PoolBase=ERROR"
}
)
-class UserGetByIdContainerTest {
+class UserDAOGetByIdContainerTest {
private static final String TEST_USERNAME = "testuser";
private static final String TEST_PASSWORD = "testpass";
@@ -60,17 +60,17 @@ void setUp() {
@Test
@DisplayName("GET /random-users/{id} should return 200 with persisted user")
void shouldReturnUserByIdWhenUserExists() {
- User user = new User();
- user.setGender("female");
- user.setFirstname("Jane");
- user.setLastname("Doe");
- user.setCivility("Ms");
- user.setEmail("jane.doe@example.com");
- user.setPhone("0600000000");
- user.setPicture("https://example.com/jane.jpg");
- user.setNationality("FR");
+ UserDAO userDAO = new UserDAO();
+ userDAO.setGender("female");
+ userDAO.setFirstname("Jane");
+ userDAO.setLastname("Doe");
+ userDAO.setCivility("Ms");
+ userDAO.setEmail("jane.doe@example.com");
+ userDAO.setPhone("0600000000");
+ userDAO.setPicture("https://example.com/jane.jpg");
+ userDAO.setNationality("FR");
- User saved = userRepository.saveAndFlush(user);
+ UserDAO saved = userRepository.saveAndFlush(userDAO);
ResponseEntity response = restTemplate.withBasicAuth(TEST_USERNAME, TEST_PASSWORD).getForEntity(
"/random-users/{id}",
diff --git a/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserHandlerTest.java b/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserDAOHandlerTest.java
similarity index 78%
rename from src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserHandlerTest.java
rename to src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserDAOHandlerTest.java
index 3ff8b59..6f8c19d 100644
--- a/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserHandlerTest.java
+++ b/src/test/java/com/xpeho/spring_boot_java_random_user/presentation/UserDAOHandlerTest.java
@@ -3,16 +3,19 @@
import com.xpeho.spring_boot_java_random_user.domain.entities.PaginatedUsers;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserEntity;
import com.xpeho.spring_boot_java_random_user.domain.entities.UserFilter;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest;
import com.xpeho.spring_boot_java_random_user.domain.enums.Gender;
import com.xpeho.spring_boot_java_random_user.domain.enums.UserSource;
import com.xpeho.spring_boot_java_random_user.domain.exceptions.UserNotFoundException;
import com.xpeho.spring_boot_java_random_user.domain.usecases.*;
+import com.xpeho.spring_boot_java_random_user.presentation.dto.UserRequest;
import com.xpeho.spring_boot_java_random_user.presentation.handlers.UserHandler;
import com.xpeho.spring_boot_java_random_user.presentation.dto.UserResponseDTO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -22,7 +25,7 @@
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
-class UserHandlerTest {
+class UserDAOHandlerTest {
private FetchAndSaveRandomUsersUseCase fetchAndSaveRandomUsersUseCase;
private UpdateRandomUserUseCase updateRandomUserUseCase;
@@ -109,40 +112,43 @@ void shouldReturnNotFoundWhenGetUserByIdFails() {
void shouldReturnOkWhenUpdateRandomUserSucceeds() {
UserRequest request = new UserRequest("female", "Jane", "Doe", "Ms", "jane@example.com", "0622222222", "jane.jpg", "FR");
UserEntity updated = new UserEntity(7L, "female", "Jane", "Doe", "Ms", "jane@example.com", "0622222222", "jane.jpg", "FR");
- when(updateRandomUserUseCase.execute(7, request)).thenReturn(updated);
+ UserEntity expectedEntity = new UserEntity(null, "female", "Jane", "Doe", "Ms", "jane@example.com", "0622222222", "jane.jpg", "FR");
+ when(updateRandomUserUseCase.execute(7, expectedEntity)).thenReturn(updated);
ResponseEntity response = userHandler.updateRandomUser(7, request);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertEquals(updated, response.getBody());
- verify(updateRandomUserUseCase, times(1)).execute(7, request);
+ verify(updateRandomUserUseCase, times(1)).execute(7, expectedEntity);
}
@Test
@DisplayName("Should return 404 when updateRandomUser throws UserNotFoundException")
void shouldReturnNotFoundWhenUpdateRandomUserFails() {
UserRequest request = new UserRequest("male", "Bob", "Brown", "Mr", "bob@example.com", "0633333333", "bob.jpg", "DE");
- when(updateRandomUserUseCase.execute(123, request)).thenThrow(new UserNotFoundException(123));
+ UserEntity expectedEntity = new UserEntity(null, "male", "Bob", "Brown", "Mr", "bob@example.com", "0633333333", "bob.jpg", "DE");
+ when(updateRandomUserUseCase.execute(123, expectedEntity)).thenThrow(new UserNotFoundException(123));
ResponseEntity response = userHandler.updateRandomUser(123, request);
assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
assertNull(response.getBody());
- verify(updateRandomUserUseCase, times(1)).execute(123, request);
+ verify(updateRandomUserUseCase, times(1)).execute(123, expectedEntity);
}
@Test
@DisplayName("Should return 201 and created user when createUser succeeds")
void shouldReturnCreatedWhenCreateUserSucceeds() {
UserRequest request = new UserRequest("female", "Emma", "Stone", "Ms", "emma@example.com", "0644444444", "emma.jpg", "FR");
+ UserEntity expectedEntity = new UserEntity(null, "female", "Emma", "Stone", "Ms", "emma@example.com", "0644444444", "emma.jpg", "FR");
UserEntity created = new UserEntity(10L, "female", "Emma", "Stone", "Ms", "emma@example.com", "0644444444", "emma.jpg", "FR");
- when(createUserUseCase.execute(request)).thenReturn(created);
+ when(createUserUseCase.execute(expectedEntity)).thenReturn(created);
ResponseEntity response = userHandler.createUser(request);
assertEquals(HttpStatus.CREATED, response.getStatusCode());
assertEquals(created, response.getBody());
- verify(createUserUseCase, times(1)).execute(request);
+ verify(createUserUseCase, times(1)).execute(expectedEntity);
}
@Test
@@ -167,34 +173,36 @@ void shouldLogWarningWhenDeleteUserByIdFails() {
}
@Test
- @DisplayName("Should return 200 and filtered users when filterUsers succeeds")
+ @DisplayName("Should return 200 and filtered page when filterUsers succeeds")
void shouldReturnOkWhenFilterUsersSucceeds() {
UserFilter filter = new UserFilter(Gender.MALE, null, null, null, null, null, "FR");
List users = List.of(
new UserEntity(1L, "male", "John", "Doe", "Mr", "john@example.com", "0600000000", "pic.jpg", "FR")
);
- when(filterUsersUseCase.execute(filter)).thenReturn(users);
+ Page page = new PageImpl<>(users, PageRequest.of(0, 20), 1);
+ when(filterUsersUseCase.execute(filter, PageRequest.of(0, 20))).thenReturn(page);
- ResponseEntity> response = userHandler.filterUsers(Gender.MALE, null, null, null, null, null, "FR");
+ ResponseEntity> response = userHandler.filterUsers(Gender.MALE, null, null, null, null, null, "FR", 0, 20);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
- assertEquals(1, response.getBody().size());
- assertEquals(users, response.getBody());
- verify(filterUsersUseCase, times(1)).execute(filter);
+ assertEquals(1, response.getBody().getTotalElements());
+ assertEquals(users, response.getBody().getContent());
+ verify(filterUsersUseCase, times(1)).execute(filter, PageRequest.of(0, 20));
}
@Test
- @DisplayName("Should return 200 and empty list when no users match filter")
+ @DisplayName("Should return 200 and empty page when no users match filter")
void shouldReturnOkWithEmptyListWhenNoUsersMatchFilter() {
UserFilter filter = new UserFilter(null, "NonExistent", null, null, null, null, null);
- when(filterUsersUseCase.execute(filter)).thenReturn(List.of());
+ Page emptyPage = new PageImpl<>(List.of(), PageRequest.of(0, 20), 0);
+ when(filterUsersUseCase.execute(filter, PageRequest.of(0, 20))).thenReturn(emptyPage);
- ResponseEntity> response = userHandler.filterUsers(null, "NonExistent", null, null, null, null, null);
+ ResponseEntity> response = userHandler.filterUsers(null, "NonExistent", null, null, null, null, null, 0, 20);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody());
assertTrue(response.getBody().isEmpty());
- verify(filterUsersUseCase, times(1)).execute(filter);
+ verify(filterUsersUseCase, times(1)).execute(filter, PageRequest.of(0, 20));
}
}
diff --git a/src/test/java/feature/CucumberIntegrationTest.java b/src/test/java/features/CucumberIntegrationTest.java
similarity index 96%
rename from src/test/java/feature/CucumberIntegrationTest.java
rename to src/test/java/features/CucumberIntegrationTest.java
index 88a7029..ec1ddaa 100644
--- a/src/test/java/feature/CucumberIntegrationTest.java
+++ b/src/test/java/features/CucumberIntegrationTest.java
@@ -1,4 +1,4 @@
-package feature;
+package features;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
@@ -11,7 +11,7 @@
@Suite
@IncludeEngines("cucumber")
@SelectClasspathResource("features")
-@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "feature")
+@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "features")
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty")
public class CucumberIntegrationTest {
diff --git a/src/test/java/feature/CucumberTypeConfig.java b/src/test/java/features/CucumberTypeConfig.java
similarity index 66%
rename from src/test/java/feature/CucumberTypeConfig.java
rename to src/test/java/features/CucumberTypeConfig.java
index c89ab6d..85a34d8 100644
--- a/src/test/java/feature/CucumberTypeConfig.java
+++ b/src/test/java/features/CucumberTypeConfig.java
@@ -1,25 +1,25 @@
-package feature;
+package features;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest;
+import com.xpeho.spring_boot_java_random_user.presentation.dto.UserRequest;
import io.cucumber.java.DataTableType;
import java.util.List;
import java.util.Map;
/**
- * Cucumber converters — transforment automatiquement les données
- * des fichiers .feature en objets Java typés.
+ * Cucumber converters — automatically transform data
+ * from .feature files into typed Java objects.
*/
public class CucumberTypeConfig {
/**
- * Représente une ligne de vérification field/expected dans une DataTable.
+ * Represents a field/expected verification row in a DataTable.
*/
public record FieldAssertion(String field, String expected) {}
/**
- * Convertit chaque ligne de la DataTable (2 colonnes sans en-tête)
- * en un objet FieldAssertion.
+ * Converts each DataTable row (2 columns without header)
+ * into a FieldAssertion object.
*/
@DataTableType
public FieldAssertion fieldAssertion(List row) {
@@ -33,8 +33,8 @@ public FieldAssertion fieldAssertion(List row) {
}
/**
- * Convertit une ligne de DataTable (Map) en UserRequest.
- * Utilisable dans les .feature avec des tables à en-têtes.
+ * Converts a DataTable row (Map) into a UserRequest.
+ * Usable in .feature files with header-based tables.
*/
@DataTableType
public UserRequest userRequest(Map row) {
diff --git a/src/test/java/feature/SpringIntegrationTest.java b/src/test/java/features/SpringIntegrationTest.java
similarity index 99%
rename from src/test/java/feature/SpringIntegrationTest.java
rename to src/test/java/features/SpringIntegrationTest.java
index a3d8d66..66a6495 100644
--- a/src/test/java/feature/SpringIntegrationTest.java
+++ b/src/test/java/features/SpringIntegrationTest.java
@@ -1,4 +1,4 @@
-package feature;
+package features;
import com.xpeho.spring_boot_java_random_user.SpringBootJavaRandomUserApplication;
import io.cucumber.spring.CucumberContextConfiguration;
diff --git a/src/test/java/feature/StepDefinition.java b/src/test/java/features/StepDefinition.java
similarity index 97%
rename from src/test/java/feature/StepDefinition.java
rename to src/test/java/features/StepDefinition.java
index afb3443..6a6303a 100644
--- a/src/test/java/feature/StepDefinition.java
+++ b/src/test/java/features/StepDefinition.java
@@ -1,9 +1,9 @@
-package feature;
+package features;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.xpeho.spring_boot_java_random_user.domain.entities.UserRequest;
-import feature.CucumberTypeConfig.FieldAssertion;
+import com.xpeho.spring_boot_java_random_user.presentation.dto.UserRequest;
+import features.CucumberTypeConfig.FieldAssertion;
import io.cucumber.java.en.And;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties
index 45e847f..5c8b097 100644
--- a/src/test/resources/application-test.properties
+++ b/src/test/resources/application-test.properties
@@ -4,8 +4,8 @@ spring.datasource.username=${H2_USERNAME:myusername}
spring.datasource.password=${H2_PASSWORD:mypassword}
app.security.admin.username=testadmin
app.security.admin.password=testadminpass
-app.security.user.username=testuser
-app.security.user.password=testpass
+app.security.userDAO.username=testuser
+app.security.userDAO.password=testpass
app.security.test.username=testviewer
app.security.test.password=testviewerpass
spring.sql.init.mode=never