diff --git a/clearing-parent/company-service/pom.xml b/clearing-parent/company-service/pom.xml index cd323c846..0e041276a 100644 --- a/clearing-parent/company-service/pom.xml +++ b/clearing-parent/company-service/pom.xml @@ -36,6 +36,11 @@ com.fasterxml.jackson.core jackson-databind + + org.springframework.boot + spring-boot-starter-test + test + diff --git a/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/config/HazelcastServiceTestConfiguration.java b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/config/HazelcastServiceTestConfiguration.java new file mode 100644 index 000000000..0c7ca4069 --- /dev/null +++ b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/config/HazelcastServiceTestConfiguration.java @@ -0,0 +1,68 @@ +package ru.spcex.clearing.company.config; + +import com.hazelcast.config.*; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastInstance; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; +import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper; + +import java.util.List; +import java.util.Random; + +@Configuration +public class HazelcastServiceTestConfiguration { + private HazelcastInstance hazelcastInstance; + + private static ThreadPoolTaskExecutor createThreadPoolTaskExecutor(int maxPoolSz, boolean waitForCompletion) { + ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor(); + if (maxPoolSz > 2) { + pool.setKeepAliveSeconds(60); + pool.setAllowCoreThreadTimeOut(true); + } + pool.setCorePoolSize(maxPoolSz); + pool.setWaitForTasksToCompleteOnShutdown(waitForCompletion); + return pool; + } + + @Bean(name = "hazelcastServiceTest") + public HazelcastService hazelcastService(@Qualifier("taskExecutorHazelcastClientInitializer") ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer, @Qualifier("taskExecutorIdGeneratorAwaiter") ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter, HazelcastClientParams params) { + Config cfg = new Config(); + cfg.setInstanceName("localhost"); + + NetworkConfig networkConfig = new NetworkConfig(); + JoinConfig joinConfig = new JoinConfig(); + joinConfig.setMulticastConfig(new MulticastConfig().setEnabled(false)); + joinConfig.setTcpIpConfig(new TcpIpConfig().setEnabled(true).setMembers(List.of("127.0.0.1"))); + networkConfig.setJoin(joinConfig); + cfg.setNetworkConfig(networkConfig); + hazelcastInstance = Hazelcast.newHazelcastInstance(cfg); + HazelcastHelper.otcSystem_setStorageState(true, hazelcastInstance); + return new HazelcastService(taskExecutorHazelcastClientInitializer, taskExecutorIdGeneratorAwaiter, params); + } + + @Bean(name = "taskExecutorHazelcastClientInitializer") + public ThreadPoolTaskExecutor taskExecutorHazelcastClientInitializer() { + return createThreadPoolTaskExecutor(1, true); + } + + @Bean(name = "taskExecutorIdGeneratorAwaiter") + public ThreadPoolTaskExecutor taskExecutorIdGeneratorAwaiter() { + return createThreadPoolTaskExecutor(1, false); + } + + @Bean(name = "hazelcastClientParams") + public HazelcastClientParams getHazelcastClientParams() { + HazelcastClientParams params = new HazelcastClientParams(); + params.setLogin("dev"); + params.setPassword("dev-pass"); + params.setClusterMembers("127.0.0.1"); + params.setInstanceName("hzTestClient" + new Random().nextInt()); + params.setNearCacheConfig(new NearCacheConfig()); + return params; + } +} diff --git a/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ClearingMemberCategoryServiceTest.java b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ClearingMemberCategoryServiceTest.java new file mode 100644 index 000000000..ef7083d7a --- /dev/null +++ b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/service/ClearingMemberCategoryServiceTest.java @@ -0,0 +1,165 @@ +package ru.spcex.clearing.company.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hazelcast.core.IMap; +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.apache.kafka.clients.consumer.MockConsumer; +import org.apache.kafka.clients.consumer.OffsetResetStrategy; +import org.apache.kafka.common.TopicPartition; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import ru.clearing.classes.statics.data.generated.ClearingMemberCategory; +import ru.spcex.clearing.company.config.HazelcastServiceTestConfiguration; +import ru.spcex.clearing.company.utils.MatcherFactory.Matcher; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.BaseRequest; +import ru.spcex.clearing.platform.messaging.domain.Consts; +import ru.spcex.clearing.platform.messaging.domain.cud.common.CommonDeleteRequest; +import ru.spcex.clearing.platform.messaging.domain.cud.company.ClearingMemberCategoryUpdateRequest; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; + +import java.util.Collections; +import java.util.HashMap; + +import static ru.spcex.clearing.company.utils.MatcherFactory.usingIgnoringFieldsComparator; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { + HazelcastServiceTestConfiguration.class}) +class ClearingMemberCategoryServiceTest { + + public static final Matcher MEMBER_CATEGORY_MATCHER = usingIgnoringFieldsComparator("id"); + private static final int PARTITION = 0; + private static final String TOPIC_MEMBER_CATEGORY_UPDATE = Consts.DESTINATION_CLEARING_MEMBER_CATEGORY_UPDATE; + private static final String TOPIC_MEMBER_CATEGORY_DELETE = Consts.DESTINATION_CLEARING_MEMBER_CATEGORY_DELETE; + private static Long currentId = 0L; + + @Autowired + @Qualifier("hazelcastServiceTest") + private HazelcastService hazelcastServiceTest; + private MockConsumer mockConsumer; + + @BeforeEach + void setUp() { + mockConsumer = new MockConsumer<>(OffsetResetStrategy.EARLIEST); + } + + @Test + void clearingMemberCategoryUpdate() throws InterruptedException { + //ARRANGE + ClearingMemberCategory existsСlearingMemberCategory = new ClearingMemberCategory(); + existsСlearingMemberCategory.setId(currentId); + existsСlearingMemberCategory.setClearingMemberCategory("0000"); + + ClearingMemberCategoryUpdateRequest memberCategoryUpdateRequest = new ClearingMemberCategoryUpdateRequest(); + memberCategoryUpdateRequest.setId(currentId); + memberCategoryUpdateRequest.setClearingMemberCategory("1234"); + BaseRequest baseUpdateRequest = new BaseRequest<>(); + baseUpdateRequest.setRequestPayload(memberCategoryUpdateRequest); + baseUpdateRequest.setId(currentId); + baseUpdateRequest.setActionType(ActionType.NEW); + String jsonBaseForUpdatingRequest; + ObjectMapper objectMapper = new ObjectMapper(); + try { + jsonBaseForUpdatingRequest = objectMapper.writeValueAsString(baseUpdateRequest); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + ClearingMemberCategory predictableClearingMemberCategory = new ClearingMemberCategory(); + predictableClearingMemberCategory.setId(currentId); + predictableClearingMemberCategory.setClearingMemberCategory("1234"); + + //ACT + //service set up + ClearingMemberCategoryService clearingMemberCategoryService = new ClearingMemberCategoryService(mockConsumer, hazelcastServiceTest); + Thread.sleep(10000); + //callbacks set up + clearingMemberCategoryService.afterPropertiesSet(); + Thread.sleep(10000); + + IMap iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_ClearingMemberCategory); + iMap.put(currentId, existsСlearingMemberCategory); + + //KAFKA + mockConsumer.schedulePollTask(() -> { + mockConsumer.rebalance(Collections.singletonList(new TopicPartition(TOPIC_MEMBER_CATEGORY_UPDATE, PARTITION))); + mockConsumer.addRecord(new ConsumerRecord<>(TOPIC_MEMBER_CATEGORY_UPDATE, PARTITION, 0, "key", jsonBaseForUpdatingRequest)); + }); + HashMap startOffsetsUpdating = new HashMap<>(); + TopicPartition tpUpdating = new TopicPartition(TOPIC_MEMBER_CATEGORY_UPDATE, PARTITION); + startOffsetsUpdating.put(tpUpdating, 0L); + mockConsumer.updateBeginningOffsets(startOffsetsUpdating); + + //ASSERT + Thread.sleep(10000); + ClearingMemberCategory resultUpdating = iMap.get(currentId); + MEMBER_CATEGORY_MATCHER.assertMatch(resultUpdating, predictableClearingMemberCategory); + // Assertions.assertEquals(0, iMap.size()); + + //preparing hazelcastImdgProvider for next test + iMap.clear(); + currentId++; + } + + @Test + void clearingMemberCategoryDelete() throws InterruptedException { + //ARRANGE + ClearingMemberCategory existsСlearingMemberCategory = new ClearingMemberCategory(); + existsСlearingMemberCategory.setId(currentId); + existsСlearingMemberCategory.setClearingMemberCategory("0000"); + + CommonDeleteRequest memberCategoryDeleteRequest = new CommonDeleteRequest(); + memberCategoryDeleteRequest.setId(currentId); + + BaseRequest baseDeleteRequest = new BaseRequest<>(); + baseDeleteRequest.setRequestPayload(memberCategoryDeleteRequest); + baseDeleteRequest.setId(currentId); + baseDeleteRequest.setActionType(ActionType.NEW); + String jsonBaseForDeleteRequest; + ObjectMapper objectMapper = new ObjectMapper(); + try { + jsonBaseForDeleteRequest = objectMapper.writeValueAsString(baseDeleteRequest); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + + //ACT + //service set up + ClearingMemberCategoryService clearingMemberCategoryService = new ClearingMemberCategoryService(mockConsumer, hazelcastServiceTest); + Thread.sleep(10000); + //callbacks set up + clearingMemberCategoryService.afterPropertiesSet(); + Thread.sleep(10000); + + IMap iMap = hazelcastServiceTest.getHazelcast().getMap(IMDGDistributedNames.Map_ClearingMemberCategory); + iMap.put(currentId, existsСlearingMemberCategory); + + //KAFKA + mockConsumer.schedulePollTask(() -> { + mockConsumer.rebalance(Collections.singletonList(new TopicPartition(TOPIC_MEMBER_CATEGORY_DELETE, PARTITION))); + mockConsumer.addRecord(new ConsumerRecord<>(TOPIC_MEMBER_CATEGORY_DELETE, PARTITION, 0, "key", jsonBaseForDeleteRequest)); + }); + HashMap startOffsetsUpdating = new HashMap<>(); + TopicPartition tpDeleting = new TopicPartition(TOPIC_MEMBER_CATEGORY_DELETE, PARTITION); + startOffsetsUpdating.put(tpDeleting, 0L); + mockConsumer.updateBeginningOffsets(startOffsetsUpdating); + + //ASSERT + Thread.sleep(10000); + ClearingMemberCategory resultUpdating = iMap.get(currentId); + Assertions.assertEquals(0, iMap.size()); + + //preparing hazelcastImdgProvider for next test + iMap.clear(); + currentId++; + } +} \ No newline at end of file diff --git a/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/utils/MatcherFactory.java b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/utils/MatcherFactory.java new file mode 100644 index 000000000..e850b89ef --- /dev/null +++ b/clearing-parent/company-service/src/test/java/ru/spcex/clearing/company/utils/MatcherFactory.java @@ -0,0 +1,38 @@ +package ru.spcex.clearing.company.utils; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Factory for creating test matchers. + *

+ * Comparing actual and expected objects via AssertJ + */ +public class MatcherFactory { + + public static Matcher usingIgnoringFieldsComparator(String... fieldsToIgnore) { + return new Matcher<>(fieldsToIgnore); + } + + public static class Matcher { + private final String[] fieldsToIgnore; + + private Matcher(String... fieldsToIgnore) { + this.fieldsToIgnore = fieldsToIgnore; + } + + public void assertMatch(T actual, T expected) { + assertThat(actual).usingRecursiveComparison().ignoringFields(fieldsToIgnore).isEqualTo(expected); + } + + @SafeVarargs + public final void assertMatch(Iterable actual, T... expected) { + assertMatch(actual, Arrays.asList(expected)); + } + + public void assertMatch(Iterable actual, Iterable expected) { + assertThat(actual).usingRecursiveFieldByFieldElementComparatorIgnoringFields(fieldsToIgnore).isEqualTo(expected); + } + } +}