Spring Boot / JUnit, запустите все модульные тесты для нескольких профилей

У меня есть класс BaseTest, который состоит из нескольких тестов. Каждое испытание выполняется для каждого профиля I списка.

Я думал об использовании параметризованных значений таких как:

@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"))
}

Как бы я сказал Spring запускать каждый тест с этими разными профилями? Фактически, каждый профиль будет разговаривать с разными источниками данных (в памяти h2, внешний mysql, внешний oracle, ..) поэтому мой репозиторий / источник данных должен быть повторно инициализирован.


Я знаю, что Я могу указать @ActiveProfiles(...) и я даже могу расширить BaseTest и переопределить аннотацию ActiveProfile. Хотя это будет работать, я показываю только часть моего набора тестов. Многие мои тестовые классы простираются от BaseTest, и я не хочу создавать несколько разных заглушек профилей для каждого класса. В настоящее время работает, но уродливое решение:

  • BaseTest (@ActiveProfiles ("mysql"))
    • FooClassMySQL (аннотация от BaseTest)
      • FooClassH2 (@ActiveProfiles ("h2"))
    • BarClassMySQL (аннотация из BaseTest)
      • BarClassH2 (@ActiveProfiles ("h2"))

спасибо

2 ответов


Если вы используете Maven, вы можете указать активный профиль из командной строки (или переменную env, если необходимо):

mvn clean test -Dspring.profiles.active=h2-test

подход с параметризованным тестом может не работать в этом случае, потому что профиль должен быть указан до того, как Spring загрузит его контекст. В этом случае при выполнении параметризованного интеграционного теста контекст будет уже загружен до запуска теста Test runner. Также параметризованные тесты JUnit были изобретены по другим причинам (running unit тесты с различными рядами данных).

EDIT: также еще одна вещь - когда вы решите использовать @RunWith(Parameterized.class) вы не сможете использовать другой бегун. Во многих случаях( если не все, если дело доходит до интеграционного тестирования) вы хотите указать другой бегун, например SpringRunner.class - С параметризованным тестом вы не сможете это сделать.


профили весны не конструированы для работы в этом путе.
В вашем случае, каждый профиль использует определенный источник данных.
Таким образом, каждый из них требует загрузки Spring для запуска тестов с ожидаемым источником данных.

на самом деле, то, что вы хотите сделать, - это сделать столько Maven, сколько профилей Spring, которые вы хотите протестировать.

кроме того, сборки в локальном env должны быть как можно быстрее.
Умножение выполнения автоматизированных тестов СУБД реализация, требующая перезагрузки Spring Boot для каждого из них, не поможет.

вам не нужно указывать @ActiveProfiles .

это похоже на задачу для инструмента непрерывной интеграции, где вы можете определить задание, которое выполняет (последовательно или параллельно) каждую сборку Maven, указав конкретный профиль загрузки Spring :

mvn clean test -Dspring.profiles.active=h2

mvn clean test -Dspring.profiles.active=mysql

etc...

вы также можете попробовать выполнить его на локальном языке, написав сценарий, который выполняет выполнение из maven строит.
Но, как уже было сказано, это замедлит вашу локальную сборку, а также усложнит ее.