сеньорчикОткрыть в Telegram
← все вопросывопросы для собеседований · Тестирование на Java

Вопросы по тестированию на Java на собеседовании

Умение писать тесты — быстрый способ отличить джуна от мидла, поэтому блок про тестирование почти всегда есть. Джун показывает синтаксис @Test и знание ассертов, мидл объясняет, почему тест не должен зависеть от порядка запуска, а сюита из сотен @SpringBootTest ползёт по десять минут.

71 вопросов в банке·5 подтем·ниже разбор 9

Что спрашивают

Из чего состоит тема

Так тема разложена в тренажёре: движок ведёт прогресс по каждой подтеме отдельно и возвращает те, где вы ошибаетесь.

Разборы подтем

Конспект по каждой: что это, как отвечать вслух, на чём валятся, плюс вопросы для самопроверки.

Примеры вопросов с разбором

  1. #integration_testcontainers1 / 9
    Что описывает пирамида тестов?
    A)Много медленных e2e сверху, немного юнитов внизу
    B)Поровну юнитов, интеграционных и e2e-тестов на каждом уровне этой пирамиды
    C)Только юниты — остальные типы избыточны
    D)Много быстрых юнитов внизу, меньше интеграционных, единицы e2e сверху
    показать ответ и разбор
    +D)Много быстрых юнитов внизу, меньше интеграционных, единицы e2e сверху

    // разбор: Пирамида: широкое основание из быстрых изолированных юнитов, средний слой интеграционных (слой + реальная зависимость), узкая верхушка дорогих медленных e2e. Форма отражает баланс скорости и уверенности: основную массу багов ловят дёшево внизу, а сквозные сценарии проверяют точечно наверху. Перевёрнутая пирамида (много e2e) — медленно и хрупко.

  2. #junit_basics2 / 9
    Чем @BeforeEach отличается от @BeforeAll в JUnit 5?
    A)@BeforeEach запускается перед каждым тестом, @BeforeAll — один раз перед всеми тестами класса
    B)@BeforeEach выполняется только для параметризованных тестов, @BeforeAll — для обычных
    C)@BeforeEach вызывается после теста, @BeforeAll — до; порядок задаётся аннотацией @Order над методами
    D)Разницы нет, это синонимы из разных версий JUnit, оставленные для совместимости
    показать ответ и разбор
    +A)@BeforeEach запускается перед каждым тестом, @BeforeAll — один раз перед всеми тестами класса

    // разбор: @BeforeEach исполняется перед КАЖДЫМ тест-методом — там готовят свежее состояние (новый объект, сброшенные моки). @BeforeAll — один раз на весь класс до всех тестов, для дорогой общей подготовки; поэтому он static (без @TestInstance(PER_CLASS)). Симметрично работают @AfterEach/@AfterAll.

  3. #mockito_mocking3 / 9
    Что возвращают методы мока, созданного mock(Repo.class), до какого-либо стабинга?
    A)Бросают UnsupportedOperationException уже на первом вызове
    B)Значения по умолчанию: null для объектов, 0 для чисел, пустые коллекции
    C)Вызывают реальную реализацию Repo
    D)Возвращают случайные значения, чтобы заодно проверить устойчивость кода
    показать ответ и разбор
    +B)Значения по умолчанию: null для объектов, 0 для чисел, пустые коллекции

    // разбор: Незастабленный мок отвечает дефолтами: null для ссылочных типов, 0/false для примитивов, пустые коллекции (не null) для List/Map/Set. Реальный код не вызывается — на то он и мок. Отсюда частый NPE в тесте: метод вернул null, потому что его забыли застабить через when().thenReturn().

  4. #spring_testing4 / 9
    Что делает аннотация @SpringBootTest на тест-классе?
    A)Создаёт голый экземпляр класса вообще без какого-либо Spring-контекста
    B)Загружает только web-слой с контроллерами и подменяет сервисы моками
    C)Поднимает полный контекст приложения Spring для интеграционного теста
    D)Запускает приложение в отдельном процессе и дёргает его по сети
    показать ответ и разбор
    +C)Поднимает полный контекст приложения Spring для интеграционного теста

    // разбор: @SpringBootTest поднимает весь контекст приложения (все бины, конфигурацию) — это полноценный интеграционный тест, и потому медленный. Web-слой в изоляции — это @WebMvcTest, а не он. По умолчанию сервер не стартует (webEnvironment=MOCK); реальный порт включают RANDOM_PORT.

  5. #test_practices_tdd5 / 9
    Какой порядок шагов в цикле TDD?
    A)Red → green → refactor: падающий тест, минимум кода, затем чистка
    B)Refactor → red → green: сначала рефакторим, потом пишем падающий тест
    C)Green → red → refactor: сперва рабочий код, потом тест
    D)Написать весь код, затем все тесты, затем рефакторинг
    показать ответ и разбор
    +A)Red → green → refactor: падающий тест, минимум кода, затем чистка

    // разбор: TDD идёт циклом red-green-refactor: сначала падающий тест, фиксирующий намерение (red), затем минимум кода, чтобы он позеленел (green), затем чистка кода при зелёных тестах (refactor). Тест первым описывает поведение и служит сетью безопасности для последующего рефакторинга. Код-до-теста — это уже не TDD.

  6. #integration_testcontainers6 / 9
    Что делает Testcontainers в интеграционном тесте?
    A)Поднимает реальную зависимость (Postgres, Kafka) в Docker на время теста
    B)Подменяет базу на встроенную H2 в памяти процесса
    C)Генерирует моки для внешних сервисов по их OpenAPI
    D)Запускает сами тесты в изолированных Docker-контейнерах вместо локальной JVM
    показать ответ и разбор
    +A)Поднимает реальную зависимость (Postgres, Kafka) в Docker на время теста

    // разбор: Testcontainers стартует настоящий контейнер (Postgres, Kafka, Redis и т.п.) в Docker на время теста и гасит его после — тест работает с тем же движком, что и прод, вместо суррогата H2. Это убирает разрыв «диалекты не совпали». Моки по OpenAPI — не про него, и тесты по-прежнему исполняются в JVM.

  7. #junit_basics7 / 9
    Зачем нужен assertThrows вместо ручного try/catch с fail()?
    A)assertThrows работает быстрее, потому что не создаёт объект исключения
    B)Он лаконично проверяет, что код бросил нужное исключение, и возвращает его для проверки сообщения
    C)assertThrows — обязательный способ поймать checked-исключение в тесте
    D)Он подавляет исключения теста, оставляя его зелёным
    показать ответ и разбор
    +B)Он лаконично проверяет, что код бросил нужное исключение, и возвращает его для проверки сообщения

    // разбор: assertThrows(Ex.class, () -> code()) проверяет, что лямбда бросила именно это исключение, и возвращает пойманный объект — можно заассертить его message или причину. Ручной try/catch с fail() многословен и коварен: забыл fail() после вызова — тест молча зелёный, даже если исключения не было.

  8. #mockito_mocking8 / 9
    Как задать, что mock.findById(1) вернёт конкретный объект?
    A)mock.findById(1).set(user)
    B)verify(mock.findById(1)).thenReturn(user)
    C)when(mock.findById(1)).thenReturn(user)
    D)assertReturns(mock.findById(1), user)
    показать ответ и разбор
    +C)when(mock.findById(1)).thenReturn(user)

    // разбор: Стабинг задаётся связкой when(...).thenReturn(...): при вызове findById(1) мок отдаст user. Для исключения — thenThrow. verify — про проверку факта вызова, а не про задание ответа; assert — про утверждения о результате. Аргумент можно обобщить матчером any() или eq(1).

  9. #spring_testing9 / 9
    Что грузит слайс @WebMvcTest(OrderController.class)?
    A)Всю схему БД вместе с репозиториями и полным entity-менеджером JPA
    B)Ничего из Spring — это чистый юнит-тест контроллера
    C)Полный контекст, но с отключённой безопасностью
    D)Только web-слой: сам контроллер, MockMvc и инфраструктуру MVC
    показать ответ и разбор
    +D)Только web-слой: сам контроллер, MockMvc и инфраструктуру MVC

    // разбор: @WebMvcTest поднимает узкий срез — MVC-инфраструктуру и указанный контроллер, плюс готовый MockMvc. Сервисы и репозитории в контекст не входят: их зависимости подставляют как @MockBean. Сервер не стартует. Быстрее @SpringBootTest, потому что грузит один слой, а не всё приложение.

это 9 из 71

Ещё 62 вопросов по теме — в тренажёре, с движком повторения

Прочитать разбор и ответить самому — разные навыки. В Сеньорчике вопросы идут сессиями, а движок возвращает подтемы, где вы ошибаетесь, пока они не начнут отскакивать. Бесплатно, лимит по энергии.

Частые вопросы