added tests for saveFile method in FileService

This commit is contained in:
Rostislav Raykov
2024-10-11 17:56:21 +03:00
parent cb7f3db36f
commit 641132d2f7
7 changed files with 280 additions and 1 deletions

View File

@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static org.rostislav.quickdrop.util.DataValidator.validateObjects;
import static org.rostislav.quickdrop.util.FileEncryptionUtils.decryptFile;
import static org.rostislav.quickdrop.util.FileEncryptionUtils.encryptFile;
@@ -40,6 +41,10 @@ public class FileService {
}
public FileEntity saveFile(MultipartFile file, FileUploadRequest fileUploadRequest) {
if (!validateObjects(file, fileUploadRequest)) {
return null;
}
logger.info("File received: {}", file.getOriginalFilename());
String uuid = UUID.randomUUID().toString();

View File

@@ -0,0 +1,53 @@
package org.rostislav.quickdrop.util;
public class DataValidator {
public static boolean validateObjects(Object... objs) {
for (Object temp : objs) {
if (temp != null) {
if (temp instanceof String value) {
if (value.trim().isEmpty()) {
return false;
}
}
} else {
return false;
}
}
return true;
}
public static double nullToZero(Double value) {
if (value == null) {
return 0;
}
return value;
}
public static int nullToZero(Integer value) {
if (value == null) {
return 0;
}
return value;
}
public static long nullToZero(Long value) {
if (value == null) {
return 0;
}
return value;
}
public static boolean nullToFalse(Boolean value) {
if (value == null) {
return false;
}
return value;
}
public static String nullToEmpty(String value) {
if (value == null) {
return "";
}
return value;
}
}

View File

@@ -0,0 +1,141 @@
package org.rostislav.quickdrop;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.rostislav.quickdrop.model.FileEntity;
import org.rostislav.quickdrop.model.FileUploadRequest;
import org.rostislav.quickdrop.repository.FileRepository;
import org.rostislav.quickdrop.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.rostislav.quickdrop.TestDataContainer.*;
@SpringBootTest
@ExtendWith(MockitoExtension.class)
public class FileServiceTests {
@Nested
class SaveFileTests {
@Autowired
FileService fileService;
@MockBean
FileRepository fileRepository;
@MockBean
PasswordEncoder passwordEncoder;
// Successfully saves an unencrypted file when no password is provided
@Test
void test_save_unencrypted_file_without_password() throws IOException {
MultipartFile file = mock(MultipartFile.class);
when(file.getOriginalFilename()).thenReturn("test.txt");
when(file.getSize()).thenReturn(1024L);
when(file.getBytes()).thenReturn("test content".getBytes());
when(fileRepository.save(any(FileEntity.class))).thenReturn(getFileEntity());
FileEntity result = fileService.saveFile(file, getFileUploadRequest());
assertNotNull(result);
assertEquals("test.txt", result.name);
assertEquals("Test description", result.description);
assertEquals(1024L, result.size);
assertNull(result.passwordHash);
}
// Successfully saves an encrypted file when a password is provided
@Test
void test_save_encrypted_file_with_password() throws IOException {
MultipartFile file = mock(MultipartFile.class);
when(file.getOriginalFilename()).thenReturn("test.txt");
when(file.getSize()).thenReturn(1024L);
when(file.getBytes()).thenReturn("test content".getBytes());
FileEntity fileEntity = getFileEntity();
when(passwordEncoder.encode(anyString())).thenReturn(fileEntity.passwordHash);
when(fileRepository.save(any(FileEntity.class))).thenReturn(fileEntity);
FileEntity result = fileService.saveFile(file, getFileUploadRequest());
assertNotNull(result);
assertEquals("test.txt", result.name);
assertEquals("Test description", result.description);
assertEquals(1024L, result.size);
assertNotNull(result.passwordHash);
}
// Correctly encodes password when provided
@Test
void test_correctly_encodes_password_when_provided() throws IOException {
MultipartFile file = mock(MultipartFile.class);
when(file.getOriginalFilename()).thenReturn("test.txt");
when(file.getSize()).thenReturn(1024L);
when(file.getBytes()).thenReturn("test content".getBytes());
FileEntity fileEntity = getFileEntity();
when(passwordEncoder.encode("securePassword")).thenReturn(fileEntity.passwordHash);
when(fileRepository.save(any(FileEntity.class))).thenReturn(fileEntity);
FileEntity result = fileService.saveFile(file, getFileUploadRequest());
assertNotNull(result);
assertEquals(fileEntity.passwordHash, result.passwordHash);
}
@Test
void test_handles_empty_file_upload_request_gracefully() throws IOException {
MultipartFile file = mock(MultipartFile.class);
when(file.getOriginalFilename()).thenReturn("test.txt");
when(file.getSize()).thenReturn(1024L);
when(file.getBytes()).thenReturn("test content".getBytes());
when(fileRepository.save(any(FileEntity.class))).thenAnswer(invocation -> {
FileEntity fileEntity = invocation.getArgument(0);
fileEntity.id = 1L; // Simulate database assigning an ID
return fileEntity;
});
FileEntity result = fileService.saveFile(file, getEmptyFileUploadRequest());
assertNotNull(result);
assertEquals("test.txt", result.name);
assertNull(result.description); // Changed to match the empty request
assertEquals(1024L, result.size);
assertNull(result.passwordHash);
}
@Test
void test_handles_null_file_upload_request() {
MultipartFile file = mock(MultipartFile.class);
FileUploadRequest fileUploadRequest = null;
when(fileRepository.save(any(FileEntity.class))).thenReturn(getFileEntity());
FileEntity result = fileService.saveFile(file, fileUploadRequest);
assertNull(result);
}
@Test
void test_handle_null_or_empty_multipartfile() {
MultipartFile file = mock(MultipartFile.class);
when(file.getOriginalFilename()).thenReturn(null);
FileEntity result = fileService.saveFile(file, getFileUploadRequest());
assertNull(result);
}
}
}

View File

@@ -0,0 +1,32 @@
package org.rostislav.quickdrop;
import org.rostislav.quickdrop.model.FileEntity;
import org.rostislav.quickdrop.model.FileUploadRequest;
import java.util.UUID;
public class TestDataContainer {
public static FileEntity getFileEntity() {
FileEntity fileEntity = new FileEntity();
fileEntity.name = "test.txt";
fileEntity.uuid = UUID.randomUUID().toString();
fileEntity.description = "Test description";
fileEntity.size = 1024L;
fileEntity.keepIndefinitely = false;
fileEntity.passwordHash = "hashed-password";
return fileEntity;
}
public static FileEntity getEmptyFileEntity() {
return new FileEntity();
}
public static FileUploadRequest getFileUploadRequest() {
return new FileUploadRequest("Test description", false, "password123");
}
public static FileUploadRequest getEmptyFileUploadRequest() {
return new FileUploadRequest();
}
}

View File

@@ -1,2 +1,3 @@
logging.file.path=quickdrop.log
spring.datasource.url=jdbc:sqlite:quickdrop.db
spring.datasource.url=jdbc:sqlite:quickdrop.db
file.save.path=test-path

View File

@@ -0,0 +1,21 @@
spring.profiles.active=test
spring.application.name=quickdrop
spring.datasource.driver-class-name=org.sqlite.JDBC
spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
spring.datasource.url=jdbc:sqlite:db/quickdrop.db
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.cache=false
spring.servlet.multipart.max-file-size=1024MB
spring.servlet.multipart.max-request-size=1024MB
server.tomcat.connection-timeout=60000
file.save.path=files
file.max.age=30
logging.file.name=log/quickdrop.log
file.deletion.cron=0 0 2 * * *
app.basic.password=test
app.enable.password=false
#logging.level.org.springframework=DEBUG
#logging.level.org.hibernate=DEBUG