3

When working with azure BlobStorage I'm quite new to this topic but I managed to get it working in java. So we have some xml files saved there and collect the file list as strings. Now I've tried to create a unit tests to verify it stays working and since the getFiles() function is a very small I expected it to be very simple to test.

@Override
public List<String> getFiles(ExecutionContext context) {
    return StreamSupport.stream(blobContainerClient.listBlobs().spliterator(), true)
        .map(BlobItem::getName)
        .collect(Collectors.toList());
}

I can mock the com.azure.storage.blob.blobContainerClient and its function listBlobs, but when trying to create the PagedIterable from a simple List I cannot make it fit the right data types or it runs into an endless loop.

Since the functionality is so minimal, we would just skip to test this, but ou of curiosity I just want to know if it could be tested or what is wrong with my code:

import com.azure.core.http.rest.*;
import com.azure.core.util.IterableStream;
import com.azure.storage.blob.BlobContainerClient;
import com.azure.storage.blob.models.BlobItem;
import com.microsoft.azure.functions.ExecutionContext;
import lombok.SneakyThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import reactor.core.CoreSubscriber;
import reactor.core.Fuseable;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.Supplier;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;

class BlobstoreConnectorListFilesTest {
    private final BlobContainerClient blobContainerClientMock = mock(BlobContainerClient.class);
    private final ExecutionContext context = mock(ExecutionContext.class);

    private final String id1 = UUID.randomUUID().toString();
    private final String id2 = UUID.randomUUID().toString();

    @BeforeEach
    void setUp() {
        BlobItem item1 = mock(BlobItem.class);
        when(item1.getName()).thenReturn(id1 + ".xml");
        
        BlobItem item2 = mock(BlobItem.class);
        when(item2.getName()).thenReturn(id2 + ".xml");
        
        List<BlobItem> arrayList = new ArrayList<>();
        arrayList.add(item1);
        arrayList.add(item2);
        Mono<PagedResponse<BlobItem>> monoSource = new Mono<>() {
            private final Page<BlobItem> page = new Page<>() {
                @Override
                public IterableStream<BlobItem> getElements() {
                    return new IterableStream<>(Flux.fromIterable(arrayList));
                }

                @Override
                public String getContinuationToken() {
                    return null;
                }
            };
            final PagedResponseBase<String, BlobItem> pagedResponseBase = new PagedResponseBase<>(null, 200, null, page
                , null);

            final Fuseable.QueueSubscription<BlobItem> fuseableQueueSubscription = new Fuseable.QueueSubscription<>() {
                @Override
                public void request(long l) {
                }
                @SneakyThrows
                @Override
                public void cancel() {
                    throw new InterruptedException();
                }
                @Override
                public int size() {
                    return arrayList.size();
                }
                @Override
                public boolean isEmpty() {
                    return arrayList.isEmpty();
                }
                @Override
                public void clear() {
                    arrayList.clear();
                }
                @Override
                public BlobItem poll() {
                    var value = arrayList.stream().findFirst().orElse(null);
                    if(value!=null){
                        arrayList.remove(value);
                    }
                    return value;
                }
                @Override
                public int requestFusion(int i) {
                    return 0;
                }
            };

            @Override
            public void subscribe(CoreSubscriber<? super PagedResponse<BlobItem>> coreSubscriber) {
                coreSubscriber.onNext(pagedResponseBase);
                coreSubscriber.onSubscribe(fuseableQueueSubscription);
            }
        };
        Supplier<Mono<PagedResponse<BlobItem>>> blobItemSupplier = () -> monoSource;
        PagedFlux<BlobItem> pagedFlux = new PagedFlux<>(blobItemSupplier);
        PagedIterable<BlobItem> leaflets = new PagedIterable<>(pagedFlux);
        doReturn(leaflets).when(blobContainerClientMock).listBlobs();
    }

    @Test
    void getAllFiles() {
        BlobstoreConnector connector = new BlobstoreConnector(blobContainerClientMock);

        List<String> actual = connector.getFiles(context);
        
        assertEquals(2, actual.size());
        assertTrue(actual.stream().anyMatch(fileName -> fileName.equals(id1 + ".xml")));
        assertTrue(actual.stream().anyMatch(fileName -> fileName.equals(id2 + ".xml")));
    }
}
S. Roder
  • 63
  • 1
  • 6
  • When rephrasing the question title, the related question [Mocking azure blob storage in unit tests](https://stackoverflow.com/questions/18611237/mocking-azure-blob-storage-in-unit-tests) came up but it seems to be overkill here or is this the only solution? – S. Roder Jan 11 '22 at 11:42

0 Answers0