← Назад к вопросам

Можно ли добавлять параметры в тестовом методе?

2.0 Middle🔥 151 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Можно ли добавлять параметры в тестовом методе

Ответ: Да, можно! Но это зависит от версии JUnit. Вот полное объяснение:

1. JUnit 4 vs JUnit 5 (различие)

JUnit 4: БЕЗ параметров в test методе

import org.junit.Test;

public class CalculatorTest {
    
    @Test
    public void testAddition() {
        // ✓ Без параметров
        Calculator calc = new Calculator();
        int result = calc.add(2, 3);
        assertEquals(5, result);
    }
    
    // ✗ Это не будет работать в JUnit 4
    @Test
    public void testAdditionWithParam(int a, int b) {
        // JUnit 4 не знает, как заполнить параметры
        // Тест не будет выполнен
    }
}

JUnit 5: С параметрами! (Parameterized Tests)

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class CalculatorTest {
    
    // ✓ С параметрами
    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3, 4, 5})
    public void testEvenNumbers(int number) {
        // Тест выполнится 5 раз с разными значениями
        assertTrue(number > 0);
    }
    
    // ✓ Несколько параметров
    @ParameterizedTest
    @CsvSource({
        "1, 2, 3",
        "2, 3, 5",
        "10, 20, 30"
    })
    public void testAddition(int a, int b, int expected) {
        Calculator calc = new Calculator();
        assertEquals(expected, calc.add(a, b));
    }
}

2. Способы добавлять параметры в JUnit 5

Способ 1: @ValueSource (одно значение)

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class ParameterizedTestsExample {
    
    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3, 4, 5})
    public void testNumber(int num) {
        assertTrue(num > 0);
    }
    
    @ParameterizedTest
    @ValueSource(strings = {"apple", "banana", "cherry"})
    public void testString(String fruit) {
        assertNotNull(fruit);
        assertTrue(fruit.length() > 0);
    }
}

Способ 2: @CsvSource (несколько значений)

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

public class CsvSourceExample {
    
    // Формат: "значение1, значение2, ..., ожидаемый_результат"
    @ParameterizedTest
    @CsvSource({
        "2, 3, 5",
        "10, 20, 30",
        "-1, 1, 0",
        "100, 0, 100"
    })
    public void testAdd(int a, int b, int expected) {
        Calculator calc = new Calculator();
        assertEquals(expected, calc.add(a, b));
    }
    
    // С именами столбцов (более читаемо)
    @ParameterizedTest(name = "тест: {0} + {1} = {2}")
    @CsvSource({
        "2, 3, 5",
        "10, 20, 30"
    })
    public void testAddWithName(int a, int b, int expected) {
        assertEquals(expected, a + b);
    }
}

Способ 3: @CsvFileSource (из файла)

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;

public class CsvFileSourceExample {
    
    @ParameterizedTest
    @CsvFileSource(resources = "/test-data.csv", numLinesToSkip = 1)
    public void testFromFile(String name, int age, String city) {
        assertNotNull(name);
        assertTrue(age > 0);
    }
}

/*
В файле src/test/resources/test-data.csv:
name,age,city
Alice,25,New York
Bob,30,London
Charlie,35,Paris
*/

Способ 4: @MethodSource (из метода)

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;

public class MethodSourceExample {
    
    // Помощник-метод, предоставляющий параметры
    static Stream<String> provideStrings() {
        return Stream.of("apple", "banana", "cherry");
    }
    
    @ParameterizedTest
    @MethodSource("provideStrings")
    public void testWithMethod(String fruit) {
        assertNotNull(fruit);
    }
    
    // С несколькими параметрами
    static Stream<org.junit.jupiter.params.provider.Arguments> provideNumbers() {
        return Stream.of(
            org.junit.jupiter.params.provider.Arguments.of(2, 3, 5),
            org.junit.jupiter.params.provider.Arguments.of(10, 20, 30),
            org.junit.jupiter.params.provider.Arguments.of(-1, 1, 0)
        );
    }
    
    @ParameterizedTest
    @MethodSource("provideNumbers")
    public void testAddFromMethod(int a, int b, int expected) {
        assertEquals(expected, a + b);
    }
}

Способ 5: @ArgumentsSource (кастомный провайдер)

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import java.util.stream.Stream;

public class ArgumentsSourceExample {
    
    // Кастомный провайдер
    static class StringsProvider implements ArgumentsProvider {
        @Override
        public Stream<? extends org.junit.jupiter.params.provider.Arguments> provideArguments(
            org.junit.jupiter.params.provider.ExtensionContext context) {
            return Stream.of(
                org.junit.jupiter.params.provider.Arguments.of("test1"),
                org.junit.jupiter.params.provider.Arguments.of("test2"),
                org.junit.jupiter.params.provider.Arguments.of("test3")
            );
        }
    }
    
    @ParameterizedTest
    @ArgumentsSource(StringsProvider.class)
    public void testWithCustomProvider(String value) {
        assertNotNull(value);
    }
}

3. Dependency Injection в параметризованные тесты

Можно передавать сервисы через параметры

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class ParameterizedWithDependencyInjection {
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private UserService userService;
    
    // ✓ Параметры из @ParameterizedTest + injected dependencies
    @ParameterizedTest
    @ValueSource(strings = {"alice@example.com", "bob@example.com"})
    public void testUserCreation(String email) {
        User user = new User(email);
        User saved = userRepository.save(user);
        assertTrue(saved.getId() > 0);
    }
}

4. Обычные тесты БЕЗ параметров (JUnit 5)

Стандартный @Test

import org.junit.jupiter.api.Test;

public class StandardTests {
    
    // Обычный тест БЕЗ параметров
    @Test
    public void testAddition() {
        assertEquals(5, 2 + 3);
    }
    
    // С setUp (before each)
    private Calculator calculator;
    
    @BeforeEach
    public void setUp() {
        calculator = new Calculator();
    }
    
    @Test
    public void testMultiplication() {
        assertEquals(6, calculator.multiply(2, 3));
    }
}

5. Реальный пример: Комбинированное тестирование

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

public class ComprehensiveCalculatorTest {
    
    // Обычный тест (BDD style)
    @Test
    public void testCalculatorInitialization() {
        Calculator calc = new Calculator();
        assertNotNull(calc);
    }
    
    // Параметризованный тест (happy path)
    @ParameterizedTest(name = "{0} + {1} = {2}")
    @CsvSource({
        "0, 0, 0",
        "1, 1, 2",
        "2, 3, 5",
        "10, 20, 30",
        "-1, 1, 0",
        "-10, -20, -30"
    })
    public void testAddition(int a, int b, int expected) {
        Calculator calc = new Calculator();
        assertEquals(expected, calc.add(a, b));
    }
    
    // Параметризованный тест (edge cases)
    @ParameterizedTest
    @CsvSource({
        "100, 2, 50",
        "0, 1, 0",
        "1000000, 2, 500000"
    })
    public void testDivision(int dividend, int divisor, int expected) {
        Calculator calc = new Calculator();
        assertEquals(expected, calc.divide(dividend, divisor));
    }
    
    // Обычный тест (exception handling)
    @Test
    public void testDivisionByZeroThrowsException() {
        Calculator calc = new Calculator();
        assertThrows(ArithmeticException.class, () -> calc.divide(10, 0));
    }
}

6. Best Practices для параметризованных тестов

✓ ХОРОШО: Ясное наименование

@ParameterizedTest(name = "тест #{index}: {0} + {1} = {2}")
@CsvSource({
    "2, 3, 5",
    "10, 20, 30"
})
public void testAdd(int a, int b, int expected) {
    assertEquals(expected, a + b);
}
// Результат:
// тест #1: 2 + 3 = 5
// тест #2: 10 + 20 = 30

✓ ХОРОШО: Разделять логику тестов

public class WellOrganizedTests {
    
    // Обычные тесты
    @Test
    public void testNormalFlow() { }
    
    // Параметризованные тесты для вариаций
    @ParameterizedTest
    @CsvSource({"1,2,3", "10,20,30"})
    public void testWithDifferentInputs(int a, int b, int c) { }
    
    // Edge cases
    @Test
    public void testEdgeCase() { }
}

✗ ИЗБЕГАЙ: Слишком сложные параметры

public class AvoidComplexity {
    
    // ✗ Сложно читать
    @ParameterizedTest
    @CsvSource({
        "user1|email1|role1|true|date1",
        "user2|email2|role2|false|date2"
    })
    public void testComplex(String user, String email, String role, 
                           boolean active, String date) { }
    
    // ✓ Лучше: использовать MethodSource
    static Stream<org.junit.jupiter.params.provider.Arguments> provideUsers() {
        return Stream.of(
            org.junit.jupiter.params.provider.Arguments.of(
                new User("user1", "email1", "role1", true)
            ),
            org.junit.jupiter.params.provider.Arguments.of(
                new User("user2", "email2", "role2", false)
            )
        );
    }
    
    @ParameterizedTest
    @MethodSource("provideUsers")
    public void testClean(User user) { }
}

7. Таблица: Когда использовать какой подход

СлучайПодходПример
Простые значения@ValueSource@ValueSource(ints = {1,2,3})
Несколько параметров@CsvSource@CsvSource({"1,2,3", "4,5,6"})
Из файла@CsvFileSource@CsvFileSource(resources = "/data.csv")
Сложная логика@MethodSource@MethodSource("provideData")
Кастомная логика@ArgumentsSource@ArgumentsSource(MyProvider.class)
Без параметров@TestОбычный тест

8. Maven/Gradle зависимости для JUnit 5

<!-- Maven -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>
// Gradle
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.9.2'

Итоговый ответ

Да, можно добавлять параметры в тестовые методы (но только в JUnit 5)!

JUnit 4:

@Test
public void test() { }  // ✓ Без параметров

@Test
public void test(int param) { }  // ✗ НЕ РАБОТАЕТ

JUnit 5:

@Test
public void test() { }  // ✓ Работает (обычный тест)

@ParameterizedTest
@ValueSource(ints = {1,2,3})
public void test(int param) { }  // ✓ РАБОТАЕТ (параметризованный тест)

Способы:

  1. @ValueSource — простые значения
  2. @CsvSource — несколько параметров
  3. @CsvFileSource — из файла
  4. @MethodSource — из метода
  5. @ArgumentsSource — кастомный провайдер

Best Practice:

  • Используй параметризованные тесты для вариаций
  • Разделяй обычные и параметризованные тесты
  • Не переусложняй параметры
  • Дай ясные имена тестам с помощью name =
  • Используй @MethodSource для сложных данных