From 628699b5e8b9c7bc97d5efebecea2e545c49f137 Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Wed, 23 Apr 2025 08:45:23 -0400 Subject: [PATCH] test: simplify tests --- config-service-impl/build.gradle.kts | 1 + config-service-impl/gradle.lockfile | 20 +- .../store/DocumentConfigStoreTest.java | 180 ++++++------------ 3 files changed, 67 insertions(+), 134 deletions(-) diff --git a/config-service-impl/build.gradle.kts b/config-service-impl/build.gradle.kts index 4a84e25a..501cadc9 100644 --- a/config-service-impl/build.gradle.kts +++ b/config-service-impl/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { compileOnly(commonLibs.lombok) testImplementation(commonLibs.junit.jupiter) + testImplementation(commonLibs.mockito.junit) testImplementation(commonLibs.mockito.core) testImplementation(commonLibs.hypertrace.grpcutils.client) } diff --git a/config-service-impl/gradle.lockfile b/config-service-impl/gradle.lockfile index 5ff44502..065e711b 100644 --- a/config-service-impl/gradle.lockfile +++ b/config-service-impl/gradle.lockfile @@ -82,16 +82,22 @@ org.hypertrace.core.kafkastreams.framework:kafka-bom:0.5.4=compileClasspath,runt org.hypertrace.core.serviceframework:docstore-metrics:0.1.86=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.hypertrace.core.serviceframework:platform-metrics:0.1.86=runtimeClasspath,testRuntimeClasspath org.hypertrace.core.serviceframework:service-framework-spi:0.1.86=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-api:5.10.0=testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter-engine:5.10.0=testRuntimeClasspath -org.junit.jupiter:junit-jupiter-params:5.10.0=testCompileClasspath,testRuntimeClasspath -org.junit.jupiter:junit-jupiter:5.10.0=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-commons:1.10.0=testCompileClasspath,testRuntimeClasspath -org.junit.platform:junit-platform-engine:1.10.0=testRuntimeClasspath -org.junit:junit-bom:5.10.0=testCompileClasspath,testRuntimeClasspath +org.junit.jupiter:junit-jupiter-api:5.10.0=testCompileClasspath +org.junit.jupiter:junit-jupiter-api:5.10.1=testRuntimeClasspath +org.junit.jupiter:junit-jupiter-engine:5.10.1=testRuntimeClasspath +org.junit.jupiter:junit-jupiter-params:5.10.0=testCompileClasspath +org.junit.jupiter:junit-jupiter-params:5.10.1=testRuntimeClasspath +org.junit.jupiter:junit-jupiter:5.10.0=testCompileClasspath +org.junit.jupiter:junit-jupiter:5.10.1=testRuntimeClasspath +org.junit.platform:junit-platform-commons:1.10.0=testCompileClasspath +org.junit.platform:junit-platform-commons:1.10.1=testRuntimeClasspath +org.junit.platform:junit-platform-engine:1.10.1=testRuntimeClasspath +org.junit:junit-bom:5.10.0=testCompileClasspath +org.junit:junit-bom:5.10.1=testRuntimeClasspath org.latencyutils:LatencyUtils:2.0.3=runtimeClasspath,testRuntimeClasspath org.lz4:lz4-java:1.8.0=runtimeClasspath,testRuntimeClasspath org.mockito:mockito-core:5.8.0=testCompileClasspath,testRuntimeClasspath +org.mockito:mockito-junit-jupiter:5.8.0=testCompileClasspath,testRuntimeClasspath org.mongodb:bson-record-codec:5.2.0=runtimeClasspath,testRuntimeClasspath org.mongodb:bson:5.2.0=runtimeClasspath,testRuntimeClasspath org.mongodb:mongodb-driver-core:5.2.0=runtimeClasspath,testRuntimeClasspath diff --git a/config-service-impl/src/test/java/org/hypertrace/config/service/store/DocumentConfigStoreTest.java b/config-service-impl/src/test/java/org/hypertrace/config/service/store/DocumentConfigStoreTest.java index c84dfbb3..0643b3f3 100644 --- a/config-service-impl/src/test/java/org/hypertrace/config/service/store/DocumentConfigStoreTest.java +++ b/config-service-impl/src/test/java/org/hypertrace/config/service/store/DocumentConfigStoreTest.java @@ -1,5 +1,6 @@ package org.hypertrace.config.service.store; +import static java.util.Collections.emptyList; import static org.hypertrace.config.service.TestUtils.CONTEXT1; import static org.hypertrace.config.service.TestUtils.RESOURCE_NAME; import static org.hypertrace.config.service.TestUtils.RESOURCE_NAMESPACE; @@ -12,6 +13,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -53,14 +55,19 @@ import org.hypertrace.core.documentstore.expression.impl.LogicalExpression; import org.hypertrace.core.documentstore.expression.impl.RelationalExpression; import org.hypertrace.core.documentstore.expression.type.FilterTypeExpression; -import org.hypertrace.core.documentstore.metric.DocStoreMetricProvider; import org.hypertrace.core.documentstore.model.options.QueryOptions; import org.hypertrace.core.documentstore.query.Query; import org.hypertrace.core.documentstore.query.SortingSpec; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +@ExtendWith(MockitoExtension.class) class DocumentConfigStoreTest { private static final long CONFIG_VERSION = 5; @@ -72,17 +79,19 @@ class DocumentConfigStoreTest { private static Value config1 = getConfig1(); private static Value config2 = getConfig2(); private static ConfigResourceContext configResourceContext = getConfigResourceContext(); - private static Collection collection; - private DocumentConfigStore configStore; - private Clock mockClock; - private FilterBuilder filterBuilder; - @BeforeEach() + private Collection collection; + @Mock private Clock mockClock; + @Mock private FilterBuilder filterBuilder; + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Datastore mockDatastore; + + @InjectMocks private DocumentConfigStore configStore; + + @BeforeEach void beforeEach() { - collection = mock(Collection.class); - this.mockClock = mock(Clock.class); - this.filterBuilder = mock(FilterBuilder.class); - this.configStore = new DocumentConfigStore(mockClock, new MockDatastore()); + this.collection = mockDatastore.getCollection(CONFIGURATIONS_COLLECTION); } @Test @@ -192,10 +201,7 @@ void WriteConfigForUpdateWithUpsertCondition() throws IOException { .setValue(Values.of("v2"))))) .build(); - org.hypertrace.core.documentstore.Filter docFilter = - new org.hypertrace.core.documentstore.Filter(); when(request.getUpsertCondition()).thenReturn(upsertCondition); - when(filterBuilder.buildDocStoreFilter(upsertCondition)).thenReturn(docFilter); UpsertedConfig upsertedConfig = configStore.writeConfig(configResourceContext, USER_ID, request, USER_EMAIL); assertEquals(config2, upsertedConfig.getConfig()); @@ -222,7 +228,6 @@ void WriteConfigForUpdateWithUpsertCondition() throws IOException { document); // failed upsert condition - when(updateResult.getUpdatedCount()).thenReturn(0L); assertThrows( StatusRuntimeException.class, () -> configStore.writeConfig(configResourceContext, USER_ID, request, USER_EMAIL)); @@ -283,7 +288,7 @@ void getAllConfigs() throws IOException { new ConfigResource(RESOURCE_NAME, RESOURCE_NAMESPACE, TENANT_ID), Filter.getDefaultInstance(), // for empty filter Pagination.getDefaultInstance(), - Collections.emptyList()); + emptyList()); assertEquals(2, contextSpecificConfigList.size()); assertEquals( @@ -370,30 +375,6 @@ void writeAllConfigs() throws IOException { @Test void buildQuery_withDefaultPagination() throws Exception { - // Arrange - ConfigResource configResource = - new ConfigResource(RESOURCE_NAMESPACE, RESOURCE_NAME, "tenant1"); - Filter filter = Filter.getDefaultInstance(); - Pagination pagination = Pagination.getDefaultInstance(); // Default pagination - - // Create a mock for CloseableIterator - CloseableIterator mockIterator = mock(CloseableIterator.class); - when(mockIterator.hasNext()).thenReturn(false); // No documents to process - - // Mock the collection.query to return the mock iterator - when(collection.query(any(Query.class), any(QueryOptions.class))).thenReturn(mockIterator); - - // Act - configStore.getAllConfigs(configResource, filter, pagination, Collections.emptyList()); - - // Capture the Query object passed to collection.query - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - verify(collection).query(queryCaptor.capture(), any(QueryOptions.class)); - - // Assert the properties of the captured Query - Query capturedQuery = queryCaptor.getValue(); - assertNotNull(capturedQuery); - List expectedSorts = Arrays.asList( SortingSpec.of( @@ -402,47 +383,39 @@ void buildQuery_withDefaultPagination() throws Exception { SortingSpec.of( IdentifierExpression.of("creationTimestamp"), org.hypertrace.core.documentstore.expression.operators.SortOrder.DESC)); - assertEquals(expectedSorts, capturedQuery.getSorts()); + + configStore.getAllConfigs( + new ConfigResource(RESOURCE_NAMESPACE, RESOURCE_NAME, "tenant1"), + Filter.getDefaultInstance(), + Pagination.getDefaultInstance(), + emptyList()); + + verify(collection) + .query( + argThat(query -> query.getSorts().equals(expectedSorts)), + any(QueryOptions.class)); } @Test void buildQuery_withCustomPagination() throws IOException { - ConfigResource configResource = - new ConfigResource(RESOURCE_NAMESPACE, RESOURCE_NAME, "tenant1"); - Filter filter = Filter.getDefaultInstance(); Pagination pagination = Pagination.newBuilder().setOffset(10).setLimit(20).build(); - List sortByList = Collections.emptyList(); - - // Create a mock for CloseableIterator - CloseableIterator mockIterator = mock(CloseableIterator.class); - when(mockIterator.hasNext()).thenReturn(false); // No documents to process - - // Mock the collection.query to return the mock iterator - when(collection.query(any(Query.class), any(QueryOptions.class))).thenReturn(mockIterator); - - // Act - configStore.getAllConfigs(configResource, filter, pagination, sortByList); - - // Capture the Query object passed to collection.query - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - verify(collection).query(queryCaptor.capture(), any(QueryOptions.class)); - - // Assert the properties of the captured Query - Query capturedQuery = queryCaptor.getValue(); - assertNotNull(capturedQuery); - org.hypertrace.core.documentstore.query.Pagination expectedPagination = org.hypertrace.core.documentstore.query.Pagination.builder().offset(10).limit(20).build(); - assertEquals(expectedPagination, capturedQuery.getPagination().get()); + + configStore.getAllConfigs( + new ConfigResource(RESOURCE_NAMESPACE, RESOURCE_NAME, "tenant1"), + Filter.getDefaultInstance(), + pagination, + emptyList()); + + verify(collection) + .query( + argThat(query -> query.getPagination().orElseThrow().equals(expectedPagination)), + any(QueryOptions.class)); } @Test void buildQuery_withCustomSorting() throws IOException { - ConfigResource configResource = - new ConfigResource(RESOURCE_NAMESPACE, RESOURCE_NAME, "tenant1"); - Filter filter = Filter.getDefaultInstance(); - Pagination pagination = Pagination.getDefaultInstance(); - org.hypertrace.config.service.v1.Selection selection = org.hypertrace.config.service.v1.Selection.newBuilder() .setConfigJsonPath("test.path") @@ -452,24 +425,7 @@ void buildQuery_withCustomSorting() throws IOException { .setSelection(selection) .setSortOrder(SortOrder.SORT_ORDER_DESC) .build(); - List sortByList = Collections.singletonList(sortBy); - // Create a mock for CloseableIterator - CloseableIterator mockIterator = mock(CloseableIterator.class); - when(mockIterator.hasNext()).thenReturn(false); // No documents to process - - // Mock the collection.query to return the mock iterator - when(collection.query(any(Query.class), any(QueryOptions.class))).thenReturn(mockIterator); - - // Act - configStore.getAllConfigs(configResource, filter, pagination, sortByList); - // Capture the Query object passed to collection.query - ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); - verify(collection).query(queryCaptor.capture(), any(QueryOptions.class)); - - // Assert the properties of the captured Query - Query capturedQuery = queryCaptor.getValue(); - assertNotNull(capturedQuery); List expectedSorts = Arrays.asList( SortingSpec.of( @@ -479,7 +435,14 @@ void buildQuery_withCustomSorting() throws IOException { IdentifierExpression.of("config.test.path"), org.hypertrace.core.documentstore.expression.operators.SortOrder.DESC)); - assertEquals(expectedSorts, capturedQuery.getSorts()); + configStore.getAllConfigs( + new ConfigResource(RESOURCE_NAMESPACE, RESOURCE_NAME, "tenant1"), + Filter.getDefaultInstance(), + Pagination.getDefaultInstance(), + Collections.singletonList(sortBy)); + + verify(collection) + .query(argThat(query -> query.getSorts().equals(expectedSorts)), any(QueryOptions.class)); } @Test @@ -497,7 +460,7 @@ void buildQuery_withFilter() throws IOException { Filter filter = Filter.newBuilder().setRelationalFilter(relationalFilter).build(); Pagination pagination = Pagination.getDefaultInstance(); - List sortByList = Collections.emptyList(); + List sortByList = emptyList(); // Create a mock for CloseableIterator CloseableIterator mockIterator = mock(CloseableIterator.class); @@ -507,7 +470,7 @@ void buildQuery_withFilter() throws IOException { when(collection.query(any(Query.class), any(QueryOptions.class))).thenReturn(mockIterator); // Act - configStore.getAllConfigs(configResource, filter, pagination, Collections.emptyList()); + configStore.getAllConfigs(configResource, filter, pagination, emptyList()); // Capture the Query object passed to collection.query ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(Query.class); @@ -540,7 +503,7 @@ private FilterTypeExpression createExpectedFilter() { lhs, org.hypertrace.core.documentstore.expression.operators.RelationalOperator.EQ, rhs); } - private static Document getConfigDocument( + private Document getConfigDocument( String context, long version, Value config, long creationTimestamp, long updateTimestamp) { return new ConfigDocument( RESOURCE_NAME, @@ -577,41 +540,4 @@ public Document next() { return documentIterator.next(); } } - - public static class MockDatastore implements Datastore { - - @Override - public Set listCollections() { - return Collections.singleton(CONFIGURATIONS_COLLECTION); - } - - @Override - public Collection getCollection(String s) { - return collection; - } - - // default implementation for other methods as they are unused - @Override - public boolean createCollection(String s, Map map) { - return false; - } - - @Override - public boolean deleteCollection(String s) { - return false; - } - - @Override - public boolean healthCheck() { - return false; - } - - @Override - public DocStoreMetricProvider getDocStoreMetricProvider() { - return null; - } - - @Override - public void close() {} - } }