diff --git a/pom.xml b/pom.xml
index f8cc255..e3c5616 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,6 +31,9 @@
3.2.2
15.0.0
20.2
+ 5.10.0
+ 5.4.0
+ 0.8.8
@@ -65,6 +68,12 @@
spring-boot-starter-graphql
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
com.graphql-java-kickstart
graphql-java-kickstart
@@ -164,6 +173,20 @@
${minio.version}
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit-jupiter.version}
+ test
+
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
@@ -223,6 +246,49 @@
+
+ org.jacoco
+ jacoco-maven-plugin
+ ${jacoco.version}
+
+
+ default-prepare-agent
+
+ prepare-agent
+
+
+
+ report
+ prepare-package
+
+ report
+
+
+
+ check
+
+ check
+
+
+
+
+ PACKAGE
+
+
+ INSTRUCTION
+ COVEREDRATIO
+ 0.60
+
+
+
+ com.example.tasklist.service.impl
+
+
+
+
+
+
+
diff --git a/src/test/java/com/example/tasklist/config/TestConfig.java b/src/test/java/com/example/tasklist/config/TestConfig.java
new file mode 100644
index 0000000..2cb4650
--- /dev/null
+++ b/src/test/java/com/example/tasklist/config/TestConfig.java
@@ -0,0 +1,103 @@
+package com.example.tasklist.config;
+
+import com.example.tasklist.repository.TaskRepository;
+import com.example.tasklist.repository.UserRepository;
+import com.example.tasklist.service.AuthService;
+import com.example.tasklist.service.ImageService;
+import com.example.tasklist.service.TaskService;
+import com.example.tasklist.service.UserService;
+import com.example.tasklist.service.impl.AuthServiceImpl;
+import com.example.tasklist.service.impl.ImageServiceImpl;
+import com.example.tasklist.service.impl.TaskServiceImpl;
+import com.example.tasklist.service.impl.UserServiceImpl;
+import com.example.tasklist.service.props.JwtProperties;
+import com.example.tasklist.service.props.MinioProperties;
+import com.example.tasklist.web.security.JwtTokenProvider;
+import com.example.tasklist.web.security.JwtUserDetailsService;
+import io.minio.MinioClient;
+import lombok.RequiredArgsConstructor;
+import org.mockito.Mockito;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+@TestConfiguration
+@RequiredArgsConstructor
+public class TestConfig {
+
+ private final UserRepository userRepository;
+ private final TaskRepository taskRepository;
+ private final AuthenticationManager authenticationManager;
+
+ @Bean
+ @Primary
+ public PasswordEncoder testPasswordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+
+ @Bean
+ public JwtProperties jwtProperties() {
+ JwtProperties jwtProperties = new JwtProperties();
+ jwtProperties.setSecret(
+ "dmdqdmphdmpndmVjdmplZ2VzamdjdnJzY2p2cnZyY2dzYWNia2hh"
+ );
+ return jwtProperties;
+ }
+
+ @Bean
+ @Primary
+ public UserDetailsService userDetailsService() {
+ return new JwtUserDetailsService(userService());
+ }
+
+ @Bean
+ public MinioClient minioClient() {
+ return Mockito.mock(MinioClient.class);
+ }
+
+ @Bean
+ public MinioProperties minioProperties() {
+ MinioProperties properties = new MinioProperties();
+ properties.setBucket("images");
+ return properties;
+ }
+
+ @Bean
+ @Primary
+ public ImageService imageService() {
+ return new ImageServiceImpl(minioClient(), minioProperties());
+ }
+
+ @Bean
+ public JwtTokenProvider tokenProvider() {
+ return new JwtTokenProvider(jwtProperties(),
+ userDetailsService(),
+ userService());
+ }
+
+ @Bean
+ @Primary
+ public UserService userService() {
+ return new UserServiceImpl(userRepository, testPasswordEncoder());
+ }
+
+ @Bean
+ @Primary
+ public TaskService taskService() {
+ return new TaskServiceImpl(taskRepository,
+ imageService());
+ }
+
+ @Bean
+ @Primary
+ public AuthService authService() {
+ return new AuthServiceImpl(authenticationManager,
+ userService(),
+ tokenProvider());
+ }
+
+}
diff --git a/src/test/java/com/example/tasklist/service/impl/AuthServiceImplTest.java b/src/test/java/com/example/tasklist/service/impl/AuthServiceImplTest.java
new file mode 100644
index 0000000..f2e94ec
--- /dev/null
+++ b/src/test/java/com/example/tasklist/service/impl/AuthServiceImplTest.java
@@ -0,0 +1,117 @@
+package com.example.tasklist.service.impl;
+
+import com.example.tasklist.config.TestConfig;
+import com.example.tasklist.domain.exception.ResourceNotFoundException;
+import com.example.tasklist.domain.user.Role;
+import com.example.tasklist.domain.user.User;
+import com.example.tasklist.repository.TaskRepository;
+import com.example.tasklist.repository.UserRepository;
+import com.example.tasklist.service.UserService;
+import com.example.tasklist.web.dto.auth.JwtRequest;
+import com.example.tasklist.web.dto.auth.JwtResponse;
+import com.example.tasklist.web.security.JwtTokenProvider;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.util.Collections;
+import java.util.Set;
+
+@ExtendWith(SpringExtension.class)
+@ActiveProfiles("test")
+@Import(TestConfig.class)
+@ExtendWith(MockitoExtension.class)
+public class AuthServiceImplTest {
+
+ @MockBean
+ private AuthenticationManager authenticationManager;
+
+ @MockBean
+ private UserService userService;
+
+ @MockBean
+ private UserRepository userRepository;
+
+ @MockBean
+ private TaskRepository taskRepository;
+
+ @MockBean
+ private JwtTokenProvider tokenProvider;
+
+ @Autowired
+ private AuthServiceImpl authService;
+
+ @Test
+ void login() {
+ Long userId = 1L;
+ String username = "username";
+ String password = "password";
+ Set roles = Collections.emptySet();
+ String accessToken = "accessToken";
+ String refreshToken = "refreshToken";
+ JwtRequest request = new JwtRequest();
+ request.setUsername(username);
+ request.setPassword(password);
+ User user = new User();
+ user.setId(userId);
+ user.setUsername(username);
+ user.setRoles(roles);
+ Mockito.when(userService.getByUsername(username))
+ .thenReturn(user);
+ Mockito.when(tokenProvider.createAccessToken(userId, username, roles))
+ .thenReturn(accessToken);
+ Mockito.when(tokenProvider.createRefreshToken(userId, username))
+ .thenReturn(refreshToken);
+ JwtResponse response = authService.login(request);
+ Mockito.verify(authenticationManager)
+ .authenticate(
+ new UsernamePasswordAuthenticationToken(
+ request.getUsername(),
+ request.getPassword()
+ )
+ );
+ Assertions.assertEquals(username, response.getUsername());
+ Assertions.assertEquals(userId, response.getId());
+ Assertions.assertNotNull(response.getAccessToken());
+ Assertions.assertNotNull(response.getRefreshToken());
+ }
+
+ @Test
+ void loginWithIncorrectUsername() {
+ String username = "username";
+ String password = "password";
+ JwtRequest request = new JwtRequest();
+ request.setUsername(username);
+ request.setPassword(password);
+ Mockito.when(userService.getByUsername(username))
+ .thenThrow(ResourceNotFoundException.class);
+ Mockito.verifyNoInteractions(tokenProvider);
+ Assertions.assertThrows(ResourceNotFoundException.class,
+ () -> authService.login(request));
+ }
+
+ @Test
+ void refresh() {
+ String accessToken = "accessToken";
+ String refreshToken = "refreshToken";
+ String newRefreshToken = "newRefreshToken";
+ JwtResponse response = new JwtResponse();
+ response.setAccessToken(accessToken);
+ response.setRefreshToken(newRefreshToken);
+ Mockito.when(tokenProvider.refreshUserTokens(refreshToken))
+ .thenReturn(response);
+ JwtResponse testResponse = authService.refresh(refreshToken);
+ Mockito.verify(tokenProvider).refreshUserTokens(refreshToken);
+ Assertions.assertEquals(response, testResponse);
+ }
+
+}
diff --git a/src/test/java/com/example/tasklist/service/impl/TaskServiceImplTest.java b/src/test/java/com/example/tasklist/service/impl/TaskServiceImplTest.java
new file mode 100644
index 0000000..d9d833b
--- /dev/null
+++ b/src/test/java/com/example/tasklist/service/impl/TaskServiceImplTest.java
@@ -0,0 +1,145 @@
+package com.example.tasklist.service.impl;
+
+import com.example.tasklist.config.TestConfig;
+import com.example.tasklist.domain.exception.ResourceNotFoundException;
+import com.example.tasklist.domain.task.Status;
+import com.example.tasklist.domain.task.Task;
+import com.example.tasklist.domain.task.TaskImage;
+import com.example.tasklist.repository.TaskRepository;
+import com.example.tasklist.repository.UserRepository;
+import com.example.tasklist.service.ImageService;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@ExtendWith(SpringExtension.class)
+@ActiveProfiles("test")
+@Import(TestConfig.class)
+@ExtendWith(MockitoExtension.class)
+public class TaskServiceImplTest {
+
+ @MockBean
+ private TaskRepository taskRepository;
+
+ @MockBean
+ private ImageService imageService;
+
+ @MockBean
+ private UserRepository userRepository;
+
+ @MockBean
+ private AuthenticationManager authenticationManager;
+
+ @Autowired
+ private TaskServiceImpl taskService;
+
+ @Test
+ void getById() {
+ Long id = 1L;
+ Task task = new Task();
+ task.setId(id);
+ Mockito.when(taskRepository.findById(id))
+ .thenReturn(Optional.of(task));
+ Task testTask = taskService.getById(id);
+ Mockito.verify(taskRepository).findById(id);
+ Assertions.assertEquals(task, testTask);
+ }
+
+ @Test
+ void getByIdWithNotExistingId() {
+ Long id = 1L;
+ Mockito.when(taskRepository.findById(id))
+ .thenReturn(Optional.empty());
+ Assertions.assertThrows(ResourceNotFoundException.class,
+ () -> taskService.getById(id));
+ Mockito.verify(taskRepository).findById(id);
+ }
+
+ @Test
+ void getAllByUserId() {
+ Long userId = 1L;
+ List tasks = new ArrayList<>();
+ for (int i = 0; i < 6; i++) {
+ tasks.add(new Task());
+ }
+ Mockito.when(taskRepository.findAllByUserId(userId))
+ .thenReturn(tasks);
+ List testTasks = taskService.getAllByUserId(userId);
+ Mockito.verify(taskRepository).findAllByUserId(userId);
+ Assertions.assertEquals(tasks, testTasks);
+ }
+
+ @Test
+ void update() {
+ Task task = new Task();
+ task.setId(1L);
+ task.setTitle("title");
+ task.setDescription("description");
+ task.setExpirationDate(LocalDateTime.now());
+ task.setStatus(Status.DONE);
+ Task testTask = taskService.update(task);
+ Mockito.verify(taskRepository).save(task);
+ Assertions.assertEquals(task, testTask);
+ }
+
+ @Test
+ void updateWithNullStatus() {
+ Task task = new Task();
+ task.setId(1L);
+ task.setTitle("title");
+ task.setDescription("description");
+ task.setExpirationDate(LocalDateTime.now());
+ Task testTask = taskService.update(task);
+ Mockito.verify(taskRepository).save(task);
+ Assertions.assertEquals(Status.TODO, testTask.getStatus());
+ }
+
+ @Test
+ void create() {
+ Long taskId = 1L;
+ Long userId = 1L;
+ Task task = new Task();
+ Mockito.doAnswer(invocationOnMock -> {
+ Task savedTask = invocationOnMock.getArgument(0);
+ savedTask.setId(taskId);
+ return savedTask;
+ })
+ .when(taskRepository).save(task);
+ Task testTask = taskService.create(task, userId);
+ Mockito.verify(taskRepository).save(task);
+ Assertions.assertNotNull(testTask.getId());
+ Mockito.verify(taskRepository).assignTask(userId, task.getId());
+ }
+
+ @Test
+ void delete() {
+ Long id = 1L;
+ taskService.delete(id);
+ Mockito.verify(taskRepository).deleteById(id);
+ }
+
+ @Test
+ void uploadImage() {
+ Long id = 1L;
+ String imageName = "imageName";
+ TaskImage taskImage = new TaskImage();
+ Mockito.when(imageService.upload(taskImage))
+ .thenReturn(imageName);
+ taskService.uploadImage(id, taskImage);
+ Mockito.verify(taskRepository).addImage(id, imageName);
+ }
+
+}
diff --git a/src/test/java/com/example/tasklist/service/impl/UserServiceImplTest.java b/src/test/java/com/example/tasklist/service/impl/UserServiceImplTest.java
new file mode 100644
index 0000000..fd9b1cf
--- /dev/null
+++ b/src/test/java/com/example/tasklist/service/impl/UserServiceImplTest.java
@@ -0,0 +1,165 @@
+package com.example.tasklist.service.impl;
+
+import com.example.tasklist.config.TestConfig;
+import com.example.tasklist.domain.exception.ResourceNotFoundException;
+import com.example.tasklist.domain.user.Role;
+import com.example.tasklist.domain.user.User;
+import com.example.tasklist.repository.TaskRepository;
+import com.example.tasklist.repository.UserRepository;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Import;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.util.Optional;
+import java.util.Set;
+
+@ExtendWith(SpringExtension.class)
+@ActiveProfiles("test")
+@Import(TestConfig.class)
+@ExtendWith(MockitoExtension.class)
+public class UserServiceImplTest {
+
+ @MockBean
+ private UserRepository userRepository;
+
+ @MockBean
+ private TaskRepository taskRepository;
+
+ @MockBean
+ private AuthenticationManager authenticationManager;
+
+ @MockBean
+ private PasswordEncoder passwordEncoder;
+
+ @Autowired
+ private UserServiceImpl userService;
+
+ @Test
+ void getById() {
+ Long id = 1L;
+ User user = new User();
+ user.setId(id);
+ Mockito.when(userRepository.findById(id))
+ .thenReturn(Optional.of(user));
+ User testUser = userService.getById(id);
+ Mockito.verify(userRepository).findById(id);
+ Assertions.assertEquals(user, testUser);
+ }
+
+ @Test
+ void getByIdWithNotExistingId() {
+ Long id = 1L;
+ Mockito.when(userRepository.findById(id))
+ .thenReturn(Optional.empty());
+ Assertions.assertThrows(ResourceNotFoundException.class,
+ () -> userService.getById(id));
+ Mockito.verify(userRepository).findById(id);
+ }
+
+ @Test
+ void getByUsername() {
+ String username = "username";
+ User user = new User();
+ user.setUsername(username);
+ Mockito.when(userRepository.findByUsername(username))
+ .thenReturn(Optional.of(user));
+ User testUser = userService.getByUsername(username);
+ Mockito.verify(userRepository).findByUsername(username);
+ Assertions.assertEquals(user, testUser);
+ }
+
+ @Test
+ void getByUsernameWithNotExistingUsername() {
+ String username = "username";
+ Mockito.when(userRepository.findByUsername(username))
+ .thenReturn(Optional.empty());
+ Assertions.assertThrows(ResourceNotFoundException.class,
+ () -> userService.getByUsername(username));
+ Mockito.verify(userRepository).findByUsername(username);
+ }
+
+ @Test
+ void update() {
+ String password = "password";
+ User user = new User();
+ user.setPassword(password);
+ userService.update(user);
+ Mockito.verify(passwordEncoder).encode(password);
+ Mockito.verify(userRepository).save(user);
+ }
+
+ @Test
+ void isTaskOwner() {
+ Long userId = 1L;
+ Long taskId = 1L;
+ Mockito.when(userRepository.isTaskOwner(userId, taskId))
+ .thenReturn(true);
+ boolean isOwner = userService.isTaskOwner(userId, taskId);
+ Mockito.verify(userRepository).isTaskOwner(userId, taskId);
+ Assertions.assertTrue(isOwner);
+ }
+
+ @Test
+ void create() {
+ String username = "username";
+ String password = "password";
+ User user = new User();
+ user.setUsername(username);
+ user.setPassword(password);
+ user.setPasswordConfirmation(password);
+ Mockito.when(userRepository.findByUsername(username))
+ .thenReturn(Optional.empty());
+ User testUser = userService.create(user);
+ Mockito.verify(userRepository).save(user);
+ Mockito.verify(passwordEncoder).encode(password);
+ Assertions.assertEquals(Set.of(Role.ROLE_USER), testUser.getRoles());
+ }
+
+ @Test
+ void createWithExistingUsername() {
+ String username = "username";
+ String password = "password";
+ User user = new User();
+ user.setUsername(username);
+ user.setPassword(password);
+ user.setPasswordConfirmation(password);
+ Mockito.when(userRepository.findByUsername(username))
+ .thenReturn(Optional.of(new User()));
+ Assertions.assertThrows(IllegalStateException.class,
+ () -> userService.create(user));
+ Mockito.verify(userRepository, Mockito.never()).save(user);
+ }
+
+ @Test
+ void createWithDifferentPasswords() {
+ String username = "username";
+ String password = "password";
+ String passwordConfirmation = "passwordConfirmation";
+ User user = new User();
+ user.setUsername(username);
+ user.setPassword(password);
+ user.setPasswordConfirmation(passwordConfirmation);
+ Mockito.when(userRepository.findByUsername(username))
+ .thenReturn(Optional.empty());
+ Assertions.assertThrows(IllegalStateException.class,
+ () -> userService.create(user));
+ Mockito.verify(userRepository, Mockito.never()).save(user);
+ }
+
+ @Test
+ void delete() {
+ Long id = 1L;
+ userService.delete(id);
+ Mockito.verify(userRepository).deleteById(id);
+ }
+
+}