More Tests
diff --git a/modules/spring-sessions/src/test/java/org/apache/ignite/spring/sessions/IgniteHttpSessionConfigurationTests.java b/modules/spring-sessions/src/test/java/org/apache/ignite/spring/sessions/IgniteHttpSessionConfigurationTests.java
new file mode 100644
index 0000000..0ee0516
--- /dev/null
+++ b/modules/spring-sessions/src/test/java/org/apache/ignite/spring/sessions/IgniteHttpSessionConfigurationTests.java
@@ -0,0 +1,425 @@
+package org.apache.ignite.spring.sessions;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentMatchers;
+
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.annotation.Order;
+import org.springframework.session.FlushMode;
+import org.springframework.session.IndexResolver;
+import org.springframework.session.SaveMode;
+import org.springframework.session.Session;
+import org.springframework.session.config.SessionRepositoryCustomizer;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for {@link IgniteHttpSessionConfiguration}.
+ */
+class IgniteHttpSessionConfigurationTests {
+
+    private static final String MAP_NAME = "spring:test:sessions";
+
+    private static final int MAX_INACTIVE_INTERVAL_IN_SECONDS = 600;
+
+    private AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+
+    @AfterEach
+    void closeContext() {
+        if (this.context != null) {
+            this.context.close();
+        }
+    }
+
+    @Test
+    void noIgniteConfiguration() {
+        assertThatExceptionOfType(BeanCreationException.class)
+                .isThrownBy(() -> registerAndRefresh(NoIgniteConfiguration.class)).withMessageContaining("Ignite");
+    }
+
+    @Test
+    void defaultConfiguration() {
+        registerAndRefresh(DefaultConfiguration.class);
+
+        assertThat(this.context.getBean(IgniteIndexedSessionRepository.class)).isNotNull();
+    }
+
+    @Test
+    void customTableName() {
+        registerAndRefresh(CustomSessionMapNameConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        IgniteHttpSessionConfiguration configuration = this.context.getBean(IgniteHttpSessionConfiguration.class);
+        assertThat(repository).isNotNull();
+        assertThat(ReflectionTestUtils.getField(configuration, "sessionMapName")).isEqualTo(MAP_NAME);
+    }
+
+    @Test
+    void setCustomSessionMapName() {
+        registerAndRefresh(BaseConfiguration.class, CustomSessionMapNameSetConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        IgniteHttpSessionConfiguration configuration = this.context.getBean(IgniteHttpSessionConfiguration.class);
+        assertThat(repository).isNotNull();
+        assertThat(ReflectionTestUtils.getField(configuration, "sessionMapName")).isEqualTo(MAP_NAME);
+    }
+
+    @Test
+    void setCustomMaxInactiveIntervalInSeconds() {
+        registerAndRefresh(BaseConfiguration.class, CustomMaxInactiveIntervalInSecondsSetConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        assertThat(repository).isNotNull();
+        assertThat(ReflectionTestUtils.getField(repository, "defaultMaxInactiveInterval"))
+                .isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
+    }
+
+    @Test
+    void customMaxInactiveIntervalInSeconds() {
+        registerAndRefresh(CustomMaxInactiveIntervalInSecondsConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        assertThat(repository).isNotNull();
+        assertThat(ReflectionTestUtils.getField(repository, "defaultMaxInactiveInterval"))
+                .isEqualTo(MAX_INACTIVE_INTERVAL_IN_SECONDS);
+    }
+
+    @Test
+    void customFlushImmediately() {
+        registerAndRefresh(CustomFlushImmediatelyConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        assertThat(repository).isNotNull();
+        assertThat(ReflectionTestUtils.getField(repository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
+    }
+
+    @Test
+    void setCustomFlushImmediately() {
+        registerAndRefresh(BaseConfiguration.class, CustomFlushImmediatelySetConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        assertThat(repository).isNotNull();
+        assertThat(ReflectionTestUtils.getField(repository, "flushMode")).isEqualTo(FlushMode.IMMEDIATE);
+    }
+
+    @Test
+    void customSaveModeAnnotation() {
+        registerAndRefresh(BaseConfiguration.class, CustomSaveModeExpressionAnnotationConfiguration.class);
+        assertThat(this.context.getBean(IgniteIndexedSessionRepository.class)).hasFieldOrPropertyWithValue("saveMode",
+                SaveMode.ALWAYS);
+    }
+
+    @Test
+    void customSaveModeSetter() {
+        registerAndRefresh(BaseConfiguration.class, CustomSaveModeExpressionSetterConfiguration.class);
+        assertThat(this.context.getBean(IgniteIndexedSessionRepository.class)).hasFieldOrPropertyWithValue("saveMode",
+                SaveMode.ALWAYS);
+    }
+
+    @Test
+    void qualifiedIgniteConfiguration() {
+        registerAndRefresh(QualifiedIgniteConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        Ignite ignite = this.context.getBean("qualifiedIgnite", Ignite.class);
+        assertThat(repository).isNotNull();
+        assertThat(ignite).isNotNull();
+        assertThat(ReflectionTestUtils.getField(repository, "sessions"))
+                .isEqualTo(QualifiedIgniteConfiguration.qualifiedIgniteSessions);
+    }
+
+    @Test
+    void primaryIgniteConfiguration() {
+        registerAndRefresh(PrimaryIgniteConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        Ignite ignite = this.context.getBean("primaryIgnite", Ignite.class);
+        assertThat(repository).isNotNull();
+        assertThat(ignite).isNotNull();
+        assertThat(ReflectionTestUtils.getField(repository, "sessions"))
+                .isEqualTo(PrimaryIgniteConfiguration.primaryIgniteSessions);
+    }
+
+    @Test
+    void qualifiedAndPrimaryIgniteConfiguration() {
+        registerAndRefresh(QualifiedAndPrimaryIgniteConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        Ignite ignite = this.context.getBean("qualifiedIgnite", Ignite.class);
+        assertThat(repository).isNotNull();
+        assertThat(ignite).isNotNull();
+        assertThat(ReflectionTestUtils.getField(repository, "sessions"))
+                .isEqualTo(QualifiedAndPrimaryIgniteConfiguration.qualifiedIgniteSessions);
+    }
+
+    @Test
+    void namedIgniteConfiguration() {
+        registerAndRefresh(NamedIgniteConfiguration.class);
+
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        Ignite ignite = this.context.getBean("ignite", Ignite.class);
+        assertThat(repository).isNotNull();
+        assertThat(ignite).isNotNull();
+        assertThat(ReflectionTestUtils.getField(repository, "sessions"))
+                .isEqualTo(NamedIgniteConfiguration.igniteSessions);
+    }
+
+    @Test
+    void multipleIgniteConfiguration() {
+        assertThatExceptionOfType(BeanCreationException.class)
+                .isThrownBy(() -> registerAndRefresh(MultipleIgniteConfiguration.class))
+                .withMessageContaining("expected single matching bean but found 2");
+    }
+
+    @Test
+    void customIndexResolverConfiguration() {
+        registerAndRefresh(CustomIndexResolverConfiguration.class);
+        IgniteIndexedSessionRepository repository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        @SuppressWarnings("unchecked")
+        IndexResolver<Session> indexResolver = this.context.getBean(IndexResolver.class);
+        assertThat(repository).isNotNull();
+        assertThat(indexResolver).isNotNull();
+        assertThat(repository).hasFieldOrPropertyWithValue("indexResolver", indexResolver);
+    }
+
+    @Test
+    void sessionRepositoryCustomizer() {
+        registerAndRefresh(SessionRepositoryCustomizerConfiguration.class);
+        IgniteIndexedSessionRepository sessionRepository = this.context.getBean(IgniteIndexedSessionRepository.class);
+        assertThat(sessionRepository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
+                MAX_INACTIVE_INTERVAL_IN_SECONDS);
+    }
+
+    private void registerAndRefresh(Class<?>... annotatedClasses) {
+        this.context.register(annotatedClasses);
+        this.context.refresh();
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession
+    static class NoIgniteConfiguration {
+
+    }
+
+    static class BaseConfiguration {
+
+        @SuppressWarnings("unchecked")
+        static IgniteCache<Object, Object> defaultIgniteSessions = mock(IgniteCache.class);
+
+        @Bean
+        Ignite defaultIgnite() {
+            Ignite ignite = mock(Ignite.class);
+            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
+                    .willReturn(defaultIgniteSessions);
+            return ignite;
+        }
+
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession
+    static class DefaultConfiguration extends BaseConfiguration {
+
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession(sessionMapName = MAP_NAME)
+    static class CustomSessionMapNameConfiguration extends BaseConfiguration {
+
+    }
+
+    @Configuration
+    static class CustomSessionMapNameSetConfiguration extends IgniteHttpSessionConfiguration {
+
+        CustomSessionMapNameSetConfiguration() {
+            setSessionMapName(MAP_NAME);
+        }
+
+    }
+
+    @Configuration
+    static class CustomMaxInactiveIntervalInSecondsSetConfiguration extends IgniteHttpSessionConfiguration {
+
+        CustomMaxInactiveIntervalInSecondsSetConfiguration() {
+            setMaxInactiveIntervalInSeconds(MAX_INACTIVE_INTERVAL_IN_SECONDS);
+        }
+
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession(maxInactiveIntervalInSeconds = MAX_INACTIVE_INTERVAL_IN_SECONDS)
+    static class CustomMaxInactiveIntervalInSecondsConfiguration extends BaseConfiguration {
+
+    }
+
+    @Configuration
+    static class CustomFlushImmediatelySetConfiguration extends IgniteHttpSessionConfiguration {
+
+        CustomFlushImmediatelySetConfiguration() {
+            setFlushMode(FlushMode.IMMEDIATE);
+        }
+
+    }
+
+    @EnableIgniteHttpSession(saveMode = SaveMode.ALWAYS)
+    static class CustomSaveModeExpressionAnnotationConfiguration {
+
+    }
+
+    @Configuration
+    static class CustomSaveModeExpressionSetterConfiguration extends IgniteHttpSessionConfiguration {
+
+        CustomSaveModeExpressionSetterConfiguration() {
+            setSaveMode(SaveMode.ALWAYS);
+        }
+
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession(flushMode = FlushMode.IMMEDIATE)
+    static class CustomFlushImmediatelyConfiguration extends BaseConfiguration {
+
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession
+    static class QualifiedIgniteConfiguration extends BaseConfiguration {
+
+        @SuppressWarnings("unchecked")
+        static IgniteCache<Object, Object> qualifiedIgniteSessions = mock(IgniteCache.class);
+
+        @Bean
+        @SpringSessionIgnite
+        Ignite qualifiedIgnite() {
+            Ignite ignite = mock(Ignite.class);
+            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
+                    .willReturn(qualifiedIgniteSessions);
+            return ignite;
+        }
+
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession
+    static class PrimaryIgniteConfiguration extends BaseConfiguration {
+
+        @SuppressWarnings("unchecked")
+        static IgniteCache<Object, Object> primaryIgniteSessions = mock(IgniteCache.class);
+
+        @Bean
+        @Primary
+        Ignite primaryIgnite() {
+            Ignite ignite = mock(Ignite.class);
+            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
+                    .willReturn(primaryIgniteSessions);
+            return ignite;
+        }
+
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession
+    static class QualifiedAndPrimaryIgniteConfiguration extends BaseConfiguration {
+
+        @SuppressWarnings("unchecked")
+        static IgniteCache<Object, Object> qualifiedIgniteSessions = mock(IgniteCache.class);
+
+        @SuppressWarnings("unchecked")
+        static IgniteCache<Object, Object> primaryIgniteSessions = mock(IgniteCache.class);
+
+        @Bean
+        @SpringSessionIgnite
+        Ignite qualifiedIgnite() {
+            Ignite ignite = mock(Ignite.class);
+            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
+                    .willReturn(qualifiedIgniteSessions);
+            return ignite;
+        }
+
+        @Bean
+        @Primary
+        Ignite primaryIgnite() {
+            Ignite ignite = mock(Ignite.class);
+            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
+                    .willReturn(primaryIgniteSessions);
+            return ignite;
+        }
+
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession
+    static class NamedIgniteConfiguration extends BaseConfiguration {
+
+        @SuppressWarnings("unchecked")
+        static IgniteCache<Object, Object> igniteSessions = mock(IgniteCache.class);
+
+        @Bean
+        Ignite ignite() {
+            Ignite ignite = mock(Ignite.class);
+            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
+                    .willReturn(igniteSessions);
+            return ignite;
+        }
+
+    }
+
+    @Configuration
+    @EnableIgniteHttpSession
+    static class MultipleIgniteConfiguration extends BaseConfiguration {
+
+        @SuppressWarnings("unchecked")
+        static IgniteCache<Object, Object> secondaryIgniteSessions = mock(IgniteCache.class);
+
+        @Bean
+        Ignite secondaryIgnite() {
+            Ignite ignite = mock(Ignite.class);
+            given(ignite.getOrCreateCache(ArgumentMatchers.<CacheConfiguration<Object, Object>>any()))
+                    .willReturn(secondaryIgniteSessions);
+            return ignite;
+        }
+
+    }
+
+    @EnableIgniteHttpSession
+    static class CustomIndexResolverConfiguration extends BaseConfiguration {
+
+        @Bean
+        @SuppressWarnings("unchecked")
+        IndexResolver<Session> indexResolver() {
+            return mock(IndexResolver.class);
+        }
+
+    }
+
+    @EnableIgniteHttpSession
+    static class SessionRepositoryCustomizerConfiguration extends BaseConfiguration {
+
+        @Bean
+        @Order(0)
+        SessionRepositoryCustomizer<IgniteIndexedSessionRepository> sessionRepositoryCustomizerOne() {
+            return (sessionRepository) -> sessionRepository.setDefaultMaxInactiveInterval(0);
+        }
+
+        @Bean
+        @Order(1)
+        SessionRepositoryCustomizer<IgniteIndexedSessionRepository> sessionRepositoryCustomizerTwo() {
+            return (sessionRepository) -> sessionRepository
+                    .setDefaultMaxInactiveInterval(MAX_INACTIVE_INTERVAL_IN_SECONDS);
+        }
+
+    }
+
+}