Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing one Spring Test Class for many different set of profiles

Tags:

java

junit

spring

I am working with:

  • Spring Framework 4.3.10
  • JUnit 4.12
  • Gradle 4.3.1

I have these two test classes

@Transactional
@RunWith(Parameterized.class)
@ContextConfiguration(classes={RootApplicationContext.class})
@ActiveProfiles(resolver=TestJdbcActiveProfilesResolver.class)
@TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class PersonaServiceImplJdbcTest {


@Transactional
@RunWith(Parameterized.class)
@ContextConfiguration(classes={RootApplicationContext.class})
@ActiveProfiles(resolver=TestHibernateActiveProfilesResolver.class)
@TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public class PersonaServiceImplHibernateTest {

The code about the @Test methods are the same for both Test classes, breaking the DRY principle, the unique difference between these two test classes is the jdbc and Hibernate profiles working together with other such as development, mysql, it internally through each TestXXXActiveProfilesResolver class variation.

Until here I have 2 test classes, breaking the DRY principle, thinking in hierarchy I am going to get 3.

How (if is possible) use one Test class where for each interaction executes two (or more) sets of profiles such as:

  • jdbc,development,mysql
  • Hibernate,development,mysql

I already have read:

  • Spring Boot / JUnit, run all unit-tests for multiple profiles

But I want avoid use commands either through Maven or Gradle, it to keep the control through the TestXXXActiveProfilesResolver classes.

like image 493
Manuel Jordan Avatar asked Oct 23 '25 16:10

Manuel Jordan


1 Answers

For JUnit 4 finally I did the following (scroll down):

@Transactional
@RunWith(Parameterized.class)
@ContextConfiguration(classes={RootApplicationContext.class})
//@ActiveProfiles() ... disable
@TestExecutionListeners(listeners={LoggingTestExecutionListener.class}, mergeMode=MergeMode.MERGE_WITH_DEFAULTS)
public abstract class PersonaServiceImplTest {

   ...

   @Autowired
   private Environment environment;

   @Before
   public void setup(){
    logger.info("Profiles: {}", Arrays.toString(environment.getActiveProfiles()));
   }

   //@Test disable
   public void someTest(){

     assertThat(...)

   }

    @ActiveProfiles(resolver=TestJdbcActiveProfilesResolver.class)
    public static class ForJdbc extends PersonaServiceImplTest {

        public ForJdbc(Persona persona){
            super(persona);
        }

        @Test
        @Override
        @Sql(scripts={"classpath:/.../script.sql"})//when be necessary
        public void someTest()(){
            super.someTest()();
        }

      }

    @ActiveProfiles(resolver=TestHibernateActiveProfilesResolver.class)
    public static class ForHibernate extends PersonaServiceImplTest {

        public ForHibernate(Persona persona){
            super(persona);
        }

        @Test
        @Override
        @Sql(scripts={"classpath:/.../script.sql"})//when be necessary
        public void someTest()(){
            super.someTest()();
        }

        ...

      }

   }

Observations:

  • The outer class must be abstract
  • The outer class must have no @ActiveProfiles declared
  • The outer class has the methods to be tested, each one must have no the @Test declared
  • Environment is optional but is useful to let know the profiles activated for each static nested class, it through the common method annotated with @Before
  • Each static nested class must be public
  • Each static nested class must extends the outer class
  • Each static nested class must have @ActiveProfiles
  • Each static nested class overrides each test method, just to use super to call the respective overridden method
  • Each static nested class, for each test overridden method, it must have the @Test.
  • @Sql can't be reused, it must be declared for each overridden method
like image 73
Manuel Jordan Avatar answered Oct 26 '25 07:10

Manuel Jordan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!