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