PoorInRichfield
PoorInRichfield

Reputation: 1578

How to Mock Azure PagedIterable<T>

I have a Java Springboot web API project that uses Azure table storage as the data store. I'd like to create a unit test to make sure that the repository is properly converting an Azure TableEntity into a custom Tag object in the repository. However, I am not able to figure-out a way to mock the Azure PagedIterable<TableEntity> that is returned by the Azure TableClient.listEntities() function.

At the core of my repository class is the following function that returns a filtered list of table entities:

    private PagedIterable<TableEntity> getFilteredTableRows(String filter, String tableName) {
        ListEntitiesOptions options = new ListEntitiesOptions().setFilter(filter);
        TableClient tableClient = tableServiceClient.getTableClient(tableName);
        PagedIterable<TableEntity> pagedIterable = tableClient.listEntities(options, null, null);
        return pagedIterable;
    }

How do I ensure the TableClient is mocked and returns a valid PagedIterable<TableEntity>?

Upvotes: 2

Views: 2928

Answers (2)

Ranjith
Ranjith

Reputation: 57

Ok, there is a bit better way. Put the needed data in a List and then pass the List iterator instead of the PagedIterable's iterator. This does not need mock for iterator. Below is the code snippet from(kotlin):

    val update1 = BinaryData.fromString("some string")
    val listUpdate = mutableListOf<BinaryData>(update1) // list of data

    val pagedIterable: PagedIterable<BinaryData> = mockk() // mockking for iterator
    every {
        pagedIterable.iterator()
    } returns listUpdate.iterator()

    mockkConstructor(xxxx::class) // Mock the SDK API to return pagedIterable
    every {
        anyConstructed<xxxx>().APICalledWhichReturnsPagedIterableType(any())
    } answers {
        pagedIterable
    }

Upvotes: -1

PoorInRichfield
PoorInRichfield

Reputation: 1578

Below is sample JUnit test class that uses Mockito to mock the Azure PagedIterable<T> object and return a single TableEntity that is mapped to a custom Tag model in the repository code.

The test setup requires four mocks:

  1. A mock Iterator
  2. A mock PagedIterable
  3. A mock TableServiceClient
  4. A mock TableClient

If there is an easier way to accomplish the same thing, I'm open to suggestions.

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
public class DocTagRepositoryTest {

    @InjectMocks
    @Spy
    DocTagRepository docTagRepository;

    @Mock
    TableServiceClient tableServiceClient;

    @Mock
    TableClient tableClient;

    private static TableEntity testTableEntity;
    private static Tag testTagObject;

    @SneakyThrows
    @BeforeAll
    public static void setup() {
        loadTableObjects();
    }

    @Test
    public void testGetTagList() {
        // Given: A request to get tags from Azure table storage...
        Iterator mockIterator = mock(Iterator.class);
        when(mockIterator.hasNext()).thenReturn(true, false);
        when(mockIterator.next()).thenReturn(testTableEntity);

        PagedIterable mockPagedTableEntities = mock(PagedIterable.class);
        when(mockPagedTableEntities.iterator()).thenReturn(mockIterator);

        when(tableServiceClient.getTableClient(Mockito.anyString())).thenReturn(tableClient);
        when(tableClient.listEntities(any(), any(), any())).thenReturn(mockPagedTableEntities);

        List<Tag> expected = new ArrayList<>();
        expected.add(testTagObject);

        // When: A call is made to the repository's getActiveTags() function...
        List<Tag> actual = docTagRepository.getActiveTags();

        // Then: Return an array of tag objects.
        assertArrayEquals(expected.toArray(), actual.toArray());
    }

    private static void loadTableObjects() {
        OffsetDateTime now = OffsetDateTime.now();
        String testUser = "buh0000";
        String rowKey = "test";
        String partitionKey = "v1";
        String activeStatus = "A";
        Map<String, Object> properties = new HashMap<>();
        properties.put("createdDate", now);
        properties.put("createdBy", testUser);
        properties.put("modifiedDate", now);
        properties.put("lastModifiedBy", testUser);
        properties.put("status", activeStatus);

        testTableEntity = new TableEntity(partitionKey, rowKey);
        testTableEntity.setProperties(properties);

        testTagObject = new Tag(partitionKey, rowKey, now, testUser, now, testUser, activeStatus);
    }
}

Upvotes: 3

Related Questions