From 0014c942a06ba3a724c7cf7c590fda6c37ed5b30 Mon Sep 17 00:00:00 2001
From: Jan Zickermann <jan.zickermann@dataport.de>
Date: Fri, 21 Feb 2025 14:47:33 +0100
Subject: [PATCH] OZG-4097 Test attachment file service

---
 .../attachment/Osi2AttachmentFileMapper.java  |   1 +
 .../attachment/Osi2AttachmentFileService.java |  26 +-
 .../Osi2AttachmentFileServiceTest.java        | 250 ++++++++++++++++++
 3 files changed, 265 insertions(+), 12 deletions(-)
 create mode 100644 src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileServiceTest.java

diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileMapper.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileMapper.java
index 74e8433..d6c3f4a 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileMapper.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileMapper.java
@@ -13,6 +13,7 @@ import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile;
 @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
 public interface Osi2AttachmentFileMapper {
 
+	// From de.ozgcloud.nachrichten.file.AttachmentFileService
 	String ATTACHMENT_FIELD_NAME = "PostfachAttachment";
 
 	OzgCloudFile mapToUploadFileMetadata(GrpcOzgFile grpcOzgFile);
diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileService.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileService.java
index 5029aa3..6e91793 100644
--- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileService.java
+++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileService.java
@@ -24,20 +24,29 @@ import net.devh.boot.grpc.client.inject.GrpcClient;
 @RequiredArgsConstructor
 public class Osi2AttachmentFileService {
 
-	@GrpcClient(GRPC_FILE_MANAGER_NAME)
-	private BinaryFileServiceGrpc.BinaryFileServiceBlockingStub binaryFilServiceStub;
+	private BinaryFileServiceGrpc.BinaryFileServiceBlockingStub binaryFileServiceStub;
 	private final Osi2AttachmentFileMapper attachmentFileMapper;
 	private final OzgCloudFileService ozgCloudFileService;
 	private final OzgCloudCallContextProvider ozgCloudCallContextProvider;
 
+	@GrpcClient(GRPC_FILE_MANAGER_NAME)
+	public void setBinaryFileServiceStub(BinaryFileServiceGrpc.BinaryFileServiceBlockingStub binaryFilServiceStubWithoutInterceptor) {
+		this.binaryFileServiceStub = binaryFilServiceStubWithoutInterceptor
+				.withInterceptors(new OzgCloudCallContextAttachingInterceptor(ozgCloudCallContextProvider));
+	}
+
 	public List<OzgCloudFile> getFileMetadataOfIds(List<String> fileIds) {
-		return getBinaryFilServiceStub().findBinaryFilesMetaData(createRequestWithFileIds(fileIds))
+		return binaryFileServiceStub.findBinaryFilesMetaData(createRequestWithFileIds(fileIds))
 				.getFileList()
 				.stream()
 				.map(attachmentFileMapper::mapToUploadFileMetadata)
 				.toList();
 	}
 
+	GrpcBinaryFilesRequest createRequestWithFileIds(List<String> fileIds) {
+		return GrpcBinaryFilesRequest.newBuilder().addAllFileId(fileIds).build();
+	}
+
 	public String uploadFileAndReturnId(AttachmentFile attachmentFile, InputStream fileInputStream) {
 		var attachmentFileId = ozgCloudFileService.uploadFile(
 				attachmentFileMapper.toOzgCloudUploadFile(attachmentFile),
@@ -46,12 +55,8 @@ public class Osi2AttachmentFileService {
 		return attachmentFileId.toString();
 	}
 
-	private GrpcBinaryFilesRequest createRequestWithFileIds(List<String> fileIds) {
-		return GrpcBinaryFilesRequest.newBuilder().addAllFileId(fileIds).build();
-	}
-
 	public InputStream downloadFileContent(String fileId) {
-		var response = getBinaryFilServiceStub().getBinaryFileContent(createRequestWithFileId(fileId));
+		var response = binaryFileServiceStub.getBinaryFileContent(createRequestWithFileId(fileId));
 		return new ConcatInputStream(new Iterator<>() {
 			@Override
 			public boolean hasNext() {
@@ -65,11 +70,8 @@ public class Osi2AttachmentFileService {
 		});
 	}
 
-	private GrpcGetBinaryFileDataRequest createRequestWithFileId(String fileId) {
+	GrpcGetBinaryFileDataRequest createRequestWithFileId(String fileId) {
 		return GrpcGetBinaryFileDataRequest.newBuilder().setFileId(fileId).build();
 	}
 
-	private BinaryFileServiceGrpc.BinaryFileServiceBlockingStub getBinaryFilServiceStub() {
-		return binaryFilServiceStub.withInterceptors(new OzgCloudCallContextAttachingInterceptor(ozgCloudCallContextProvider));
-	}
 }
diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileServiceTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileServiceTest.java
new file mode 100644
index 0000000..892e9c2
--- /dev/null
+++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/attachment/Osi2AttachmentFileServiceTest.java
@@ -0,0 +1,250 @@
+package de.ozgcloud.nachrichten.postfach.osiv2.attachment;
+
+import static de.ozgcloud.nachrichten.postfach.osiv2.factory.GrpcOzgFileTestFactory.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+
+import com.google.protobuf.ByteString;
+
+import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextAttachingInterceptor;
+import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextProvider;
+import de.ozgcloud.apilib.file.OzgCloudFile;
+import de.ozgcloud.apilib.file.OzgCloudFileId;
+import de.ozgcloud.apilib.file.OzgCloudFileService;
+import de.ozgcloud.apilib.file.OzgCloudFileTestFactory;
+import de.ozgcloud.apilib.file.OzgCloudUploadFile;
+import de.ozgcloud.apilib.file.OzgCloudUploadFileTestFactory;
+import de.ozgcloud.nachrichten.postfach.osiv2.model.AttachmentFile;
+import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcBinaryFilesRequest;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcFindFilesResponse;
+import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataResponse;
+import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile;
+import lombok.SneakyThrows;
+
+class Osi2AttachmentFileServiceTest {
+
+	@Spy
+	@InjectMocks
+	private Osi2AttachmentFileService service;
+
+	@Mock
+	private Osi2AttachmentFileMapper attachmentFileMapper;
+
+	@Mock
+	private OzgCloudFileService ozgCloudFileService;
+
+	@Mock
+	private OzgCloudCallContextProvider ozgCloudCallContextProvider;
+
+	@Mock
+	private BinaryFileServiceGrpc.BinaryFileServiceBlockingStub binaryFileServiceStubWithoutInterceptor;
+
+	@Mock
+	private BinaryFileServiceGrpc.BinaryFileServiceBlockingStub binaryFileServiceStub;
+
+	@Captor
+	private ArgumentCaptor<OzgCloudCallContextAttachingInterceptor> interceptorCaptor;
+
+	@BeforeEach
+	void setup() {
+		when(binaryFileServiceStubWithoutInterceptor.withInterceptors(interceptorCaptor.capture())).thenReturn(binaryFileServiceStub);
+		service.setBinaryFileServiceStub(binaryFileServiceStubWithoutInterceptor);
+	}
+
+	@DisplayName("should set ozg cloud call context provider")
+	@Test
+	void shouldSetOzgCloudCallContextProvider() {
+		assertThat(interceptorCaptor.getValue())
+				.extracting("callContextProvider")
+				.isEqualTo(ozgCloudCallContextProvider);
+	}
+
+
+	@DisplayName("get file metadata of ids")
+	@Nested
+	class TestGetFileMetadataOfIds {
+
+		@Mock
+		private GrpcFindFilesResponse grpcFindFilesResponse;
+
+		@Mock
+		private GrpcBinaryFilesRequest grpcBinaryFilesRequest;
+
+		@Mock
+		private GrpcOzgFile grpcOzgFile;
+
+		private final OzgCloudFile ozgCloudFile = OzgCloudFileTestFactory.create();
+
+		@BeforeEach
+		void mock() {
+			doReturn(grpcBinaryFilesRequest).when(service).createRequestWithFileIds(any());
+			when(binaryFileServiceStub.findBinaryFilesMetaData(any())).thenReturn(grpcFindFilesResponse);
+			when(grpcFindFilesResponse.getFileList()).thenReturn(List.of(grpcOzgFile));
+			when(attachmentFileMapper.mapToUploadFileMetadata(any())).thenReturn(ozgCloudFile);
+		}
+
+		@DisplayName("should call createRequestWithFileIds")
+		@Test
+		void shouldCallCreateRequestWithFileIds() {
+			getFileMetadataOfIds();
+
+			verify(service).createRequestWithFileIds(List.of(FILE_ID));
+		}
+
+		@DisplayName("should call findBinaryFilesMetaData")
+		@Test
+		void shouldCallFindBinaryFilesMetaData() {
+			getFileMetadataOfIds();
+
+			verify(binaryFileServiceStub).findBinaryFilesMetaData(grpcBinaryFilesRequest);
+		}
+
+		@DisplayName("should call map to upload file metadata")
+		@Test
+		void shouldCallMapToUploadFileMetadata() {
+			getFileMetadataOfIds();
+
+			verify(attachmentFileMapper).mapToUploadFileMetadata(grpcOzgFile);
+		}
+
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			var result = getFileMetadataOfIds();
+
+			assertThat(result).containsExactly(ozgCloudFile);
+		}
+
+		private List<OzgCloudFile> getFileMetadataOfIds() {
+			return service.getFileMetadataOfIds(List.of(FILE_ID));
+		}
+
+	}
+
+	@DisplayName("create request with file ids")
+	@Nested
+	class TestCreateRequestWithFileIds {
+
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			var result = service.createRequestWithFileIds(List.of(FILE_ID));
+
+			assertThat(result.getFileIdList()).containsExactly(FILE_ID);
+		}
+
+	}
+
+	@DisplayName("upload file and return id")
+	@Nested
+	class TestUploadFileAndReturnId {
+		@Mock
+		private InputStream inputStream;
+
+		@Mock
+		private AttachmentFile attachmentFile;
+
+		private final OzgCloudUploadFile ozgCloudUploadFile = OzgCloudUploadFileTestFactory.create();
+
+		@BeforeEach
+		void mock() {
+			when(attachmentFileMapper.toOzgCloudUploadFile(any())).thenReturn(ozgCloudUploadFile);
+			when(ozgCloudFileService.uploadFile(any(), any())).thenReturn(new OzgCloudFileId(FILE_ID));
+		}
+
+		@DisplayName("should call toOzgCloudUploadFile")
+		@Test
+		void shouldCallToOzgCloudUploadFile() {
+			uploadFileAndReturnId();
+
+			verify(attachmentFileMapper).toOzgCloudUploadFile(attachmentFile);
+		}
+
+		@DisplayName("should call uploadFile")
+		@Test
+		void shouldCallUploadFile() {
+			uploadFileAndReturnId();
+
+			verify(ozgCloudFileService).uploadFile(any(), any());
+		}
+
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			var result = uploadFileAndReturnId();
+
+			assertThat(result).isEqualTo(FILE_ID);
+		}
+
+		private String uploadFileAndReturnId() {
+			return service.uploadFileAndReturnId(attachmentFile, inputStream);
+		}
+	}
+
+	@DisplayName("download file content")
+	@Nested
+	class TestDownloadFileContent {
+
+		@Mock
+		private GrpcGetBinaryFileDataResponse response1;
+
+		@Mock
+		private ByteString chunkContent1;
+
+		@Mock
+		private GrpcGetBinaryFileDataResponse response2;
+
+		@Mock
+		private ByteString chunkContent2;
+
+		@BeforeEach
+		void mock() {
+			when(binaryFileServiceStub.getBinaryFileContent(any())).thenReturn(List.of(response1, response2).iterator());
+			when(response1.getFileContent()).thenReturn(chunkContent1);
+			when(response2.getFileContent()).thenReturn(chunkContent2);
+			when(chunkContent1.newInput()).thenReturn(new ByteArrayInputStream("abc".getBytes()));
+			when(chunkContent2.newInput()).thenReturn(new ByteArrayInputStream("def".getBytes()));
+		}
+
+
+		@DisplayName("should return")
+		@Test
+		@SneakyThrows
+		void shouldReturn() {
+			var result = service.downloadFileContent(FILE_ID);
+
+			var concatBytes = IOUtils.toByteArray(result);
+			assertThat(new String(concatBytes)).isEqualTo("abcdef");
+		}
+	}
+
+	@DisplayName("create request with file id")
+	@Nested
+	class TestCreateRequestWithFileId {
+
+		@DisplayName("should return")
+		@Test
+		void shouldReturn() {
+			var result = service.createRequestWithFileId(FILE_ID);
+
+			assertThat(result.getFileId()).isEqualTo(FILE_ID);
+		}
+	}
+
+}
\ No newline at end of file
-- 
GitLab