diff --git a/pom.xml b/pom.xml
index e79b897..897ff30 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,6 +84,7 @@
spring-test-rabbitmq
spring-test-activemq
spring-test-jpa
+ spring-test-mssql
spring-test-mysql
spring-test-postgres
spring-test-web
diff --git a/spring-test-mssql/.gitignore b/spring-test-mssql/.gitignore
new file mode 100644
index 0000000..82eca33
--- /dev/null
+++ b/spring-test-mssql/.gitignore
@@ -0,0 +1,25 @@
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/build/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
\ No newline at end of file
diff --git a/spring-test-mssql/pom.xml b/spring-test-mssql/pom.xml
new file mode 100644
index 0000000..3b4cbd1
--- /dev/null
+++ b/spring-test-mssql/pom.xml
@@ -0,0 +1,84 @@
+
+
+ 4.0.0
+
+
+ com.jupiter-tools
+ spring-boot-extensions-parent
+ 0.4
+
+
+ spring-test-mssql
+ ${parent.version}
+ jar
+
+ spring-test-mssql
+ JUnit5 utils and extensions to make integration tests for MSSQL with Spring
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 3.3.2
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ provided
+
+
+
+ com.jupiter-tools
+ spring-test-jpa
+ ${parent.version}
+
+
+
+
+ org.testcontainers
+ mssqlserver
+ 1.15.3
+ compile
+
+
+
+
+
+
+
+ com.microsoft.sqlserver
+ mssql-jdbc
+ 9.2.1.jre8
+
+
+
+
+
+ org.projectlombok
+ lombok
+ test
+
+
+
+
+
+
+
+
+ ${project.basedir}/src/main/resources
+ true
+
+
+
+
+ ${project.basedir}/src/test/resources
+ true
+
+
+
+
+
+
diff --git a/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/annotation/EnableMsSqlTestContainers.java b/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/annotation/EnableMsSqlTestContainers.java
new file mode 100644
index 0000000..147032f
--- /dev/null
+++ b/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/annotation/EnableMsSqlTestContainers.java
@@ -0,0 +1,26 @@
+package com.jupiter.tools.spring.test.mssql.annotation;
+
+import com.jupiter.tools.spring.test.jpa.extension.TraceSqlExtension;
+import com.jupiter.tools.spring.test.mssql.extension.MsSqlTcExtension;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.test.context.ActiveProfiles;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Created on 17.07.2018.
+ *
+ * Start a MSSQL container in Docker, by a test-containers library.
+ *
+ * @author Korovin Anatoliy
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@ExtendWith(MsSqlTcExtension.class)
+@ExtendWith(TraceSqlExtension.class)
+@ActiveProfiles("jupiter-tools.spring-test-mssql.test-containers")
+public @interface EnableMsSqlTestContainers {
+}
diff --git a/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlDataTest.java b/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlDataTest.java
new file mode 100644
index 0000000..616958c
--- /dev/null
+++ b/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlDataTest.java
@@ -0,0 +1,26 @@
+package com.jupiter.tools.spring.test.mssql.annotation.meta;
+
+import com.jupiter.tools.spring.test.jpa.annotation.EnableDataTest;
+import com.jupiter.tools.spring.test.jpa.annotation.EnableRiderTest;
+import com.jupiter.tools.spring.test.mssql.annotation.EnableMsSqlTestContainers;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Created on 19.07.2018.
+ *
+ * Meta-annotation for the combination of: DataTests, RiderTests
+ * and MSSQL docker container.
+ *
+ * @author Korovin Anatoliy
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@EnableDataTest
+@EnableRiderTest
+@EnableMsSqlTestContainers
+public @interface EnableMsSqlDataTest {
+}
diff --git a/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlIntegrationTest.java b/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlIntegrationTest.java
new file mode 100644
index 0000000..0845de0
--- /dev/null
+++ b/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlIntegrationTest.java
@@ -0,0 +1,27 @@
+package com.jupiter.tools.spring.test.mssql.annotation.meta;
+
+
+import com.jupiter.tools.spring.test.core.annotation.EnableIntegrationTest;
+import com.jupiter.tools.spring.test.jpa.annotation.EnableRiderTest;
+import com.jupiter.tools.spring.test.mssql.annotation.EnableMsSqlTestContainers;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Created on 19.07.2018.
+ *
+ * Meta-annotation for the combination of: IntegrationTests, RiderTests
+ * and MSSQL docker container.
+ *
+ * @author Korovin Anatoliy
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@EnableIntegrationTest
+@EnableRiderTest
+@EnableMsSqlTestContainers
+public @interface EnableMsSqlIntegrationTest {
+}
diff --git a/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/extension/MsSqlTcExtension.java b/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/extension/MsSqlTcExtension.java
new file mode 100644
index 0000000..1921d50
--- /dev/null
+++ b/spring-test-mssql/src/main/java/com/jupiter/tools/spring/test/mssql/extension/MsSqlTcExtension.java
@@ -0,0 +1,27 @@
+package com.jupiter.tools.spring.test.mssql.extension;
+
+import org.hibernate.dialect.SQLServer2012Dialect;
+import org.junit.jupiter.api.extension.Extension;
+import org.testcontainers.containers.MSSQLServerContainer;
+
+/**
+ * Created on 06.08.2018.
+ *
+ * @author Korovin Anatoliy
+ */
+public class MsSqlTcExtension implements Extension {
+
+ static {
+ System.out.println("Start MsSql testcontainers extension...\n");
+
+ MSSQLServerContainer mssql = new MSSQLServerContainer("mcr.microsoft.com/mssql/server:2022-latest")
+ .acceptLicense();
+ mssql.start();
+
+ System.setProperty("spring.datasource.driver-class-name", mssql.getDriverClassName());
+ System.setProperty("spring.datasource.url", mssql.getJdbcUrl());
+ System.setProperty("spring.datasource.username", mssql.getUsername());
+ System.setProperty("spring.datasource.password", mssql.getPassword());
+ System.setProperty("spring.jpa.properties.hibernate.dialect", SQLServer2012Dialect.class.getCanonicalName());
+ }
+}
diff --git a/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/TransactionalTestConfig.java b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/TransactionalTestConfig.java
new file mode 100644
index 0000000..9d438c2
--- /dev/null
+++ b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/TransactionalTestConfig.java
@@ -0,0 +1,86 @@
+package com.jupiter.tools.spring.test.mssql;
+
+import lombok.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.stereotype.Repository;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.*;
+import java.math.BigDecimal;
+
+/**
+ * Created on 12.07.2018.
+ *
+ * Transaction Persistence layer configuration,
+ * for testing transactional methods in wrappers and service.
+ *
+ * @author Korovin Anatoliy
+ */
+@SpringBootApplication
+@TestConfiguration
+@EnableJpaRepositories(considerNestedRepositories = true)
+@EntityScan(basePackageClasses = {TransactionalTestConfig.class})
+public class TransactionalTestConfig {
+
+ @Repository
+ public interface FooRepository extends JpaRepository {
+ @Query(value = "SELECT RAND()", nativeQuery = true)
+ Double rand();
+
+ @Query(value = "SELECT DATALENGTH('123')", nativeQuery = true)
+ String nativeQuery();
+ }
+
+ @Table(name = "foo")
+ @Entity
+ @Setter
+ @Getter
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Foo {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(columnDefinition = "decimal(9,0)")
+ private BigDecimal id;
+
+ @Column(nullable = false)
+ private String field;
+ }
+
+ @Service
+ public class TestService {
+ @Autowired
+ private FooRepository fooRepository;
+
+ @Transactional
+ public Foo ok() {
+ Foo foo = new Foo();
+ foo.setField("tru la la..");
+ return fooRepository.save(foo);
+ }
+
+ @Transactional
+ public void fail() {
+ fooRepository.save(new Foo());
+ }
+
+ @Transactional(readOnly = true)
+ public long size() {
+ return fooRepository.count();
+ }
+
+ @Transactional(isolation = Isolation.SERIALIZABLE)
+ public void clear() {
+ fooRepository.deleteAll();
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/annotation/EnableMsSqlTestContainersTest.java b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/annotation/EnableMsSqlTestContainersTest.java
new file mode 100644
index 0000000..2062954
--- /dev/null
+++ b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/annotation/EnableMsSqlTestContainersTest.java
@@ -0,0 +1,41 @@
+package com.jupiter.tools.spring.test.mssql.annotation;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+/**
+ * Created on 26.01.2019.
+ *
+ * @author Korovin Anatoliy
+ */
+@DataJpaTest
+@ExtendWith(SpringExtension.class)
+@EnableMsSqlTestContainers
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+class EnableMsSqlTestContainersTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Test
+ @Sql("/stored_procedures/test_procedure.sql")
+ void testStoredProcedure() {
+ // Arrange
+ Query query = entityManager.createNativeQuery("EXEC ANSWER_TO_THE_ULTIMATE_QUESTION");
+
+ // Act
+ int result = (int) query.getSingleResult();
+
+ //Assert
+ Assertions.assertThat(result).isEqualTo(42);
+ }
+}
diff --git a/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlDataTestTest.java b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlDataTestTest.java
new file mode 100644
index 0000000..b21665c
--- /dev/null
+++ b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlDataTestTest.java
@@ -0,0 +1,58 @@
+package com.jupiter.tools.spring.test.mssql.annotation.meta;
+
+import com.github.database.rider.core.api.dataset.DataSet;
+import com.github.database.rider.core.api.dataset.ExpectedDataSet;
+import com.jupiter.tools.spring.test.mssql.TransactionalTestConfig;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.annotation.Commit;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+/**
+ * Created on 26.01.2019.
+ *
+ * @author Korovin Anatoliy
+ */
+@EnableMsSqlDataTest
+@Import(TransactionalTestConfig.class)
+class EnableMsSqlDataTestTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Autowired
+ private TransactionalTestConfig.FooRepository repository;
+
+ @Test
+ @Sql("/stored_procedures/test_procedure.sql")
+ void testStoredProcedure() {
+ // Arrange
+ Query query = entityManager.createNativeQuery("EXEC ANSWER_TO_THE_ULTIMATE_QUESTION");
+
+ // Act
+ int result = (int) query.getSingleResult();
+
+ //Assert
+ Assertions.assertThat(result).isEqualTo(42);
+ }
+
+ @Test
+ @Commit
+ @Transactional(propagation = Propagation.NOT_SUPPORTED)
+ @DataSet(cleanBefore = true, cleanAfter = true)
+ @ExpectedDataSet(value = "/datasets/expected.json", ignoreCols = "ID")
+ void testCreate() {
+
+ repository.saveAndFlush(TransactionalTestConfig.Foo.builder()
+ .field("tru la la..")
+ .build());
+ }
+}
diff --git a/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlIntegrationTestTest.java b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlIntegrationTestTest.java
new file mode 100644
index 0000000..40f4d9f
--- /dev/null
+++ b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/annotation/meta/EnableMsSqlIntegrationTestTest.java
@@ -0,0 +1,28 @@
+package com.jupiter.tools.spring.test.mssql.annotation.meta;
+
+import com.github.database.rider.core.api.dataset.DataSet;
+import com.github.database.rider.core.api.dataset.ExpectedDataSet;
+import com.jupiter.tools.spring.test.mssql.TransactionalTestConfig;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Import;
+
+/**
+ * Created on 26.01.2019.
+ *
+ * @author Korovin Anatoliy
+ */
+@EnableMsSqlIntegrationTest
+@Import(TransactionalTestConfig.class)
+class EnableMsSqlIntegrationTestTest {
+
+ @Autowired
+ private TransactionalTestConfig.TestService testService;
+
+ @Test
+ @DataSet(cleanBefore = true, cleanAfter = true)
+ @ExpectedDataSet(value = "/datasets/expected.json", ignoreCols = "ID")
+ void testCreate() {
+ testService.ok();
+ }
+}
diff --git a/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/extension/MsSqlTcExtensionIntegrationTest.java b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/extension/MsSqlTcExtensionIntegrationTest.java
new file mode 100644
index 0000000..aee283c
--- /dev/null
+++ b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/extension/MsSqlTcExtensionIntegrationTest.java
@@ -0,0 +1,62 @@
+package com.jupiter.tools.spring.test.mssql.extension;
+
+import com.github.database.rider.core.api.dataset.DataSet;
+import com.github.database.rider.core.api.dataset.ExpectedDataSet;
+import com.github.database.rider.spring.api.DBRider;
+import com.jupiter.tools.spring.test.jpa.extension.TraceSqlExtension;
+import com.jupiter.tools.spring.test.mssql.TransactionalTestConfig;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Created on 25.01.2019.
+ *
+ * @author Korovin Anatoliy
+ */
+@DBRider
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+@ExtendWith(MsSqlTcExtension.class)
+@ExtendWith(TraceSqlExtension.class)
+@Import(TransactionalTestConfig.class)
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+class MsSqlTcExtensionIntegrationTest {
+
+ @Autowired
+ private TransactionalTestConfig.TestService testService;
+
+ @Autowired
+ private TransactionalTestConfig.FooRepository fooRepository;
+
+ @Test
+ @DataSet(cleanBefore = true, cleanAfter = true)
+ @ExpectedDataSet(value = "/datasets/expected.json", ignoreCols = "ID")
+ void testCreate() {
+ testService.ok();
+ }
+
+ @Test
+ void nativeQuery() {
+ //Act & Assert
+ assertThat(fooRepository.nativeQuery()).isEqualTo("3");
+ }
+
+ @Test
+ void hostName() {
+ // Act
+ String hostName = fooRepository.nativeQuery();
+
+ System.out.println("! Host name is " + hostName + " !");
+
+ // Assert
+ assertThat(hostName).isNotNull();
+ }
+
+}
\ No newline at end of file
diff --git a/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/extension/MsSqlTcExtensionTest.java b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/extension/MsSqlTcExtensionTest.java
new file mode 100644
index 0000000..8307493
--- /dev/null
+++ b/spring-test-mssql/src/test/java/com/jupiter/tools/spring/test/mssql/extension/MsSqlTcExtensionTest.java
@@ -0,0 +1,43 @@
+package com.jupiter.tools.spring.test.mssql.extension;
+
+import com.jupiter.tools.spring.test.jpa.extension.TraceSqlExtension;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+/**
+ * Created on 25.01.2019.
+ *
+ * @author Korovin Anatoliy
+ */
+@DataJpaTest
+@ExtendWith(SpringExtension.class)
+@ExtendWith(MsSqlTcExtension.class)
+@ExtendWith(TraceSqlExtension.class)
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+class MsSqlTcExtensionTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Test
+ @Sql("/stored_procedures/test_procedure.sql")
+ void testStoredProcedure() {
+ // Arrange
+ Query query = entityManager.createNativeQuery("EXEC ANSWER_TO_THE_ULTIMATE_QUESTION");
+
+ // Act
+ int result = (int) query.getSingleResult();
+
+ //Assert
+ Assertions.assertThat(result).isEqualTo(42);
+ }
+}
\ No newline at end of file
diff --git a/spring-test-mssql/src/test/resources/datasets/expected.json b/spring-test-mssql/src/test/resources/datasets/expected.json
new file mode 100644
index 0000000..afa716b
--- /dev/null
+++ b/spring-test-mssql/src/test/resources/datasets/expected.json
@@ -0,0 +1,8 @@
+{
+ "foo": [
+ {
+ "id": 1,
+ "field": "tru la la.."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/spring-test-mssql/src/test/resources/logback-test.xml b/spring-test-mssql/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..520993b
--- /dev/null
+++ b/spring-test-mssql/src/test/resources/logback-test.xml
@@ -0,0 +1,17 @@
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{15}) - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-test-mssql/src/test/resources/stored_procedures/test_procedure.sql b/spring-test-mssql/src/test/resources/stored_procedures/test_procedure.sql
new file mode 100644
index 0000000..fda77d1
--- /dev/null
+++ b/spring-test-mssql/src/test/resources/stored_procedures/test_procedure.sql
@@ -0,0 +1,4 @@
+CREATE PROCEDURE ANSWER_TO_THE_ULTIMATE_QUESTION AS
+BEGIN
+ SELECT 42
+END;
\ No newline at end of file