我有一个 Java Springboot Web API 项目,它使用 Azure 表存储作为数据存储。我想创建一个单元测试,以确保存储库正确地将 Azure
TableEntity
转换为存储库中的自定义 Tag
对象。但是,我无法找到一种方法来模拟 Azure PagedIterable<TableEntity>
函数返回的 Azure TableClient.listEntities()
。
我的存储库类的核心是以下函数,它返回经过过滤的表实体列表:
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;
}
如何确保
TableClient
被模拟并返回有效的 PagedIterable<TableEntity>
?
下面是示例 JUnit 测试类,它使用 Mockito 模拟 Azure
PagedIterable<T>
对象并返回映射到存储库代码中的自定义标签模型的单个 TableEntity
。
测试设置需要四个模拟:
如果有更简单的方法来完成同样的事情,我愿意接受建议。
@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);
}
}
好吧,还有更好的方法。将所需数据放入 List 中,然后传递 List 迭代器而不是 PagedIterable 的迭代器。这不需要迭代器的模拟。以下是来自(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
}