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

Frame91 picture Frame91 · Jul 19, 2017 · Viewed 7k times · Source

I have a BaseTest class which consists of several tests. Each test shall be executed for EVERY profile I list.

I thought about using Parameterized values such as:

@RunWith(Parameterized.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// @ActiveProfiles("h2-test") // <-- how to iterate over this?
public abstract class BaseTest {

@Autowired
private TestRepository test;

// to be used with Parameterized/Spring
private TestContextManager testContextManager;

public BaseTest(String profile) {
   System.setProperty("spring.profiles.active", profile);
   // TODO what now?
}

@Parameterized.Parameters
public static Collection<Object[]> data() {
  Collection<Object[]> params = new ArrayList<>();
  params.add(new Object[] {"h2-test" });
  params.add(new Object[] {"mysql-test" });
  return params;
}

@Before 
public void setUp() throws Exception {
  this.testContextManager = new TestContextManager(getClass());
  this.testContextManager.prepareTestInstance(this);
  // maybe I can spinup Spring here with my profile?
}

@Test
public void testRepository() {
  Assert.assertTrue(test.exists("foo"))
}

How would I tell Spring to run each test with these different profiles? In fact, each profile will talk to different datasources (in-memory h2, external mysql, external oracle, ..) so my repository/datasource has to be reinitialized.


I know that I can specify @ActiveProfiles(...) and I can even extend from BaseTest and override the ActiveProfile annotation. Although this will work, I only show a portion of my test-suite. Lots of my test-classes extend from BaseTest and I don't want to create several different profile-stubs for each class. Currently working, but ugly solution:

  • BaseTest (@ActiveProfiles("mysql"))
    • FooClassMySQL(annotation from BaseTest)
      • FooClassH2(@ActiveProfiles("h2"))
    • BarClassMySQL(annotation from BaseTest)
      • BarClassH2(@ActiveProfiles("h2"))

Thanks

Answer

davidxxx picture davidxxx · Jul 23, 2017

Spring profiles are not designed to work in this way.
In your case, each profile uses a specific datasource.
So each one requires a Spring Boot load to run tests with the expected datasource.

In fact, what you want to do is like making as many Maven build as Spring profiles that you want to test.

Besides, builds in local env should be as fast as possible.
Multiplying automated tests execution by DBMS implementation that requires a Spring Boot reload for each one will not help.

You should not need to specify @ActiveProfiles .

It looks rather like a task for a Continuous Integration tool where you could define a job that executes (sequentially or parallely) each Maven build by specifying a specific Spring Boot profile :

mvn clean test -Dspring.profiles.active=h2

mvn clean test -Dspring.profiles.active=mysql

etc...

You can also try to perform it in local by writing a script that performs the execution of the maven builds.
But as said, it will slowdown your local build and also complex it.