Below is code implementation for reading an azure blob , i am getting exception java.io.IOException: Underlying input stream returned zero bytes for the line reader.readLine() in while condition. Following are my codes that i have tried
@Component
@AllArgsConstructor
@Slf4j
public class AzureBlobServiceImpl implements AzureBlobService {
BlobServiceClient blobServiceClient;
AzureStorageConfiguration azureStorageConfiguration;
DownloadRetryOptions downloadRetryOptions;
@Override
public List<String> readBlobFile(String container) {
BlobContainerClient blobContainerClient = blobServiceClient.getBlobContainerClient(container);
Stream<BlobItem> blobItemsStream = blobContainerClient.listBlobs().stream();
List<String> fileList = new ArrayList<>();
Pattern pattern = Pattern.compile(azureStorageConfiguration.getInputFilePattern());
if (pattern != null) {
blobItemsStream = blobItemsStream.filter((blobItem) -> pattern.asPredicate().test(blobItem.getName()));
}
blobItemsStream.forEach((blobItem) -> {
log.info("blob found {} in the container {} with creation time {} & last modified time {}", blobItem.getName(),container,
blobItem.getProperties().getCreationTime(),blobItem.getProperties().getLastModified());
BlobClient blobClient = blobContainerClient.getBlobClient(blobItem.getName());
try (BufferedReader reader = new BufferedReader(new InputStreamReader(blobClient.openInputStream()))) {
String line;
long row = 1;
while ((line = reader.readLine()) != null) {
log.info("Row {} : {}",row, line);
//TODO write logic to insert each row in the table
row++;
}
} catch (BlobStorageException e) {
log.error("error while reading the file {}",blobItem.getName(),e);
throw new BlobReadingException("Error while reading " + blobItem.getName() +e);
}catch (Exception e) {
throw new BlobReadingException("Error occurred while processing " + blobItem.getName()+ e);
}
fileList.add(blobItem.getName());
//Archive the files and delete from inboud
archiveFile(blobItem.getName());
});
log.info("fileList: "+fileList);
return fileList;
} Following is my JUnit for the above
@ExtendWith(MockitoExtension.class)
class AzureBlobServiceImplTest {
@Mock
BlobServiceClient blobServiceClient;
@Mock
DownloadRetryOptions downloadRetryOptions;
@Mock
AzureStorageConfiguration azureStorageConfiguration;
@Mock
BlobContainerClient blobContainerClient;
@Mock
BlobClient blobClient;
@Mock
Response<Boolean> response;
@Mock
BlobDownloadResponse blobDownloadResponse;
@Mock
BlobInputStream blobInputStream;
@Mock
PagedIterable<BlobItem> iterable;
@Mock
BufferedReader bufferedReader;
@InjectMocks
AzureBlobServiceImpl azureBlobService;
@BeforeEach
void setUp() {
Assertions.assertNotNull(azureBlobService);
when(blobServiceClient.getBlobContainerClient(anyString())).thenReturn(blobContainerClient);
when(blobContainerClient.getBlobClient(anyString())).thenReturn(blobClient);
}
@AfterEach
void testMethodTearDown() {
Mockito.clearInvocations(blobServiceClient, downloadRetryOptions, azureStorageConfiguration, blobContainerClient, blobClient, response, blobDownloadResponse);
}
@Test
void read_success() throws IOException {
//String filePath = "src/test/resources/Test25Oct.txt";
// blobClient.uploadFromFile(filePath);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
BufferedReader input =
new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buffer.toByteArray())));
String line = input.readLine();
BlobItemProperties blobProps = new BlobItemProperties();
OffsetDateTime offsetDateTime = OffsetDateTime.of(2023, 10, 31, 0, 0, 0, 0, ZoneOffset.UTC);
blobProps.setCreationTime(offsetDateTime);
blobProps.setLastModified(offsetDateTime);
blobProps.setContentLength(100L);
byte[] dummyData = {1,2,3,5};
blobProps.setContentMd5(dummyData);
BlobItem blobItem1 = new BlobItem();
blobItem1.setName("blob1.txt");
blobItem1.setProperties(blobProps);
BlobItem blobItem2 = new BlobItem();
blobItem2.setName("blob2.txt");
blobItem2.setProperties(blobProps);
List<BlobItem> blobItemList = List.of(blobItem1, blobItem2);
when(blobServiceClient.getBlobContainerClient(anyString())).thenReturn(blobContainerClient);
when(blobContainerClient.listBlobs()).thenReturn(iterable);
when(blobContainerClient.listBlobs().stream()).thenReturn(blobItemList.stream());
when(blobContainerClient.getBlobClient(anyString())).thenReturn(blobClient);
when(bufferedReader.readLine())
.thenReturn("Line 1")
.thenReturn("Line 2")
.thenReturn(null);
when(blobClient.openInputStream()).thenReturn(blobInputStream);
when(azureStorageConfiguration.getInputFilePattern()).thenReturn(".*blob.*");
//test the method
List<String> fileList = azureBlobService.readBlobFile("test-container");
assertEquals(2, fileList.size());
assertEquals("blob1.txt", fileList.get(0));
assertEquals("blob2.txt", fileList.get(1));
verify(blobServiceClient, times(1)).getBlobContainerClient("test-container");
verify(blobContainerClient, times(2)).listBlobs();
verify(blobContainerClient, times(2)).getBlobClient(anyString());
verify(blobClient, times(2)).openInputStream();
}
}
Can someone please help on how i can mock the behaviour to return InoutStream for my Test class?