В чем разница между полями и переменными в Java?

Ответ

В контексте тестирования на Java (например, при написании unit-тестов с JUnit) важно понимать эти различия для корректной организации тестовых данных.

Поля (fields) класса — это переменные, объявленные на уровне класса. В тестах это часто аннотированные поля (например, @Mock, @InjectMocks, @BeforeEach) или поля для хранения общих тестовых данных.

Локальные переменные существуют только в рамках метода (например, внутри отдельного тестового метода @Test).

Пример в тестовом классе:

import org.junit.jupiter.api.*;
import static org.mockito.Mockito.*;

class PaymentServiceTest {
    // ПОЛЕ КЛАССА: мок-объект, инициализируется для всех тестовых методов
    @Mock
    private PaymentGateway mockGateway;

    // ПОЛЕ КЛАССА: тестируемый сервис, в него будет внедрён мок
    @InjectMocks
    private PaymentService paymentService;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this); // Инициализация моков
    }

    @Test
    void testSuccessfulPayment() {
        // ЛОКАЛЬНАЯ ПЕРЕМЕННАЯ: существует только в этом методе
        String transactionId = "TXN-12345";
        double amount = 100.0;

        // Настройка поведения мока (поле mockGateway)
        when(mockGateway.process(anyDouble())).thenReturn(transactionId);

        // Вызов тестируемого метода (использует поле paymentService)
        String result = paymentService.makePayment(amount);

        // Проверка утверждения
        Assertions.assertEquals(transactionId, result);
        verify(mockGateway).process(amount); // Верификация вызова мока
    }
}

Ключевое для QA: Поля @Mock/@InjectMocks переиспользуются между тестами, но их состояние может сбрасываться в @BeforeEach. Локальные переменные изолированы для каждого теста, что предотвращает нежелательные побочные эффекты.

Ответ 18+ 🔞

А, ну это же классика, ёпта! Смотри, чтобы не накосячить с тестами на Java, надо чётко понимать, где у тебя поля класса торчат, а где локальные переменные в методах юзаются. Это как отличить свою зубную щётку от общей в общаге — иначе будет пиздец.

Поля класса — это типа твоя личная собственность, которая валяется на самом виду, на уровне всего класса. Вот эти все аннотации типа @Mock, @InjectMocks — они обычно тут и болтаются. Или какие-то общие данные для всех тестов.

Локальные переменные — это штуки, которые живут только внутри одного конкретного метода. Закончился метод — и их как не бывало. Удобно, чтобы один тест другому в тарелку не насрал случайно.

Смотри пример, сейчас всё станет ясно:

import org.junit.jupiter.api.*;
import static org.mockito.Mockito.*;

class PaymentServiceTest {
    // ВОТ ЭТО ПОЛЕ КЛАССА: мок, который будет для всех тестов
    @Mock
    private PaymentGateway mockGateway;

    // И ЭТО ТОЖЕ ПОЛЕ: сюда этот мок воткнётся
    @InjectMocks
    private PaymentService paymentService;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this); // Тут всё инициализируется, бля
    }

    @Test
    void testSuccessfulPayment() {
        // А ВОТ ЭТО УЖЕ ЛОКАЛЬНАЯ ПЕРЕМЕННАЯ: только для этого метода
        String transactionId = "TXN-12345";
        double amount = 100.0;

        // Настраиваем мок (то самое поле mockGateway)
        when(mockGateway.process(anyDouble())).thenReturn(transactionId);

        // Дёргаем тестируемый сервис (поле paymentService)
        String result = paymentService.makePayment(amount);

        // Ну и проверяем, что всё заебись
        Assertions.assertEquals(transactionId, result);
        verify(mockGateway).process(amount);
    }
}

Самое главное для тестировщика: Поля с @Mock и @InjectMocks — они одни на все тесты. Но в @BeforeEach их обычно заново инициализируют, чтобы каждый тест начинался с чистого листа. А локальные переменные — они вообще святые, каждая в своём методе живёт и другим не мешает. Так и надо, чтобы не было вот этого волнения ебать, когда один тест поломает состояние для другого. Всё изолированно, красиво, доверия ебать ноль, но зато надёжно.