Как ограничить параллелизм в тестах junit 5
Краткое описание - тесты junit 5 работают на встроенной многопоточке. В каждом создаются свои юзеры(экземляры определенного класса, являющегося ядром структуры) и над ним проводится тестирование. Пришла задача ограничить пул юзеров в 20 штук. Т.е. теперь все тесты будут "цеплять" юзеров из пула и работать с ними. Дело в том, что тестов много больше чем юзеров, да и бывает что в тесте используется 2 юзера. В общем подскажите библиотеку, которая это разрулит, не хочется самому писать) Надо чтобы на юзера, подхваченного тестом, накладывался лок до завершения теста и если свободных юзеров нет в наличии, чтобы тест ждал свободного юзера.
Ответы (1 шт):
Сначала задаем конфигурацию для junit5:
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent
junit.jupiter.execution.parallel.config.strategy = fixed
junit.jupiter.execution.parallel.config.fixed.parallelism = 20
Это даст гарантию, что больше 20 потоков junit не запустит.
Далее нужно реализовать глобальный пул пользователей. Каждый тест перед запуском создает нужных ему пользователей с помощью пула. После окончания - тест возвращает пользователей в пул.
И самому реализовать несложно, а можно воспользоваться готовым из apache commons-poool.
Если у важ уже есть список объектов, то вам нужно реализовать метод makeObject из PooledObjectFactory, который будет возвращать готовые объекты один раз. Я не даю готовую реализацию и не тестровал это код, это скорее демонстрация, которая показывает, как эти приблизительно выглядит. Что-то типа :
class PrecreatedPooledObjectFactory extends BasePooledObjectFactory<User>{
List<User> users;
PrecreatedPoolObjectFactory(List<User> users) {
this.user = user;
}
public PooledObject<User> makeObject() {
User user = users.remove(user.get(0);
return new DefaultPooledObject<User>(user);
}
}
GenericObjectPoolConfig<User> config = new GenericObjectPoolConfig<>();
config.setMaxTotal(20);
List<User> precreatedUsers = ...
GenericObjectPool<User> pool = new GenericObjectPool<>(
new PrecreatedPooledObjectFactory(precreatedUsers),
config
);
И далее используете:
@BeforeEach
void setUp() {
user = pool.borrowObject();
}
@AfterEach
void tearDown() {
pool.returnObject(user);
}
Когда в пуле заканчиваются объекты, тест будет ждать в setUp пока другой тест не вернет их в пул.