[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-reactive-kak-testirovat-reaktivnyy-kod":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":15,"progress":16,"seo":17},999,"kak-testirovat-reaktivnyy-kod",31,"reactive","Reactive","⚡","Как тестировать реактивный код?","Реактивный код тестируется через StepVerifier — инструмент из reactor-test, который подписывается на Mono\u002FFlux и пошагово проверяет сигналы. Нельзя просто вызвать метод и проверить результат, потому что Mono и Flux ленивы.\n\n### StepVerifier — основной инструмент\n\n```java\n\u002F\u002F Тестирование Mono\n@Test\nvoid testFindById() {\n    Mono\u003CUser> userMono = userService.findById(1L);\n\n    StepVerifier.create(userMono)\n        .expectNextMatches(user -> user.getName().equals(\"John\"))\n        .verifyComplete();\n}\n\n\u002F\u002F Тестирование Flux\n@Test\nvoid testFindAll() {\n    Flux\u003CUser> usersFlux = userService.findAll();\n\n    StepVerifier.create(usersFlux)\n        .expectNextCount(3)\n        .verifyComplete();\n}\n\n\u002F\u002F Тестирование ошибок\n@Test\nvoid testError() {\n    Mono\u003CUser> errorMono = userService.findById(-1L);\n\n    StepVerifier.create(errorMono)\n        .expectError(NotFoundException.class)\n        .verify();\n}\n```\n\n### Тестирование с виртуальным временем\n\n```java\n@Test\nvoid testWithVirtualTime() {\n    StepVerifier.withVirtualTime(() ->\n            Flux.interval(Duration.ofHours(1)).take(3))\n        .expectSubscription()\n        .thenAwait(Duration.ofHours(3))\n        .expectNext(0L, 1L, 2L)\n        .verifyComplete();\n}\n```\n\n\u003Cdetails>\u003Csummary>TestPublisher — управляемый источник для тестов\u003C\u002Fsummary>\n\n```java\n@Test\nvoid testWithTestPublisher() {\n    TestPublisher\u003CString> testPublisher = TestPublisher.create();\n\n    Flux\u003CString> flux = testPublisher.flux()\n        .map(String::toUpperCase);\n\n    StepVerifier.create(flux)\n        .then(() -> testPublisher.emit(\"hello\", \"world\"))\n        .expectNext(\"HELLO\", \"WORLD\")\n        .verifyComplete();\n}\n\n\u002F\u002F Симуляция ошибки\n@Test\nvoid testErrorWithTestPublisher() {\n    TestPublisher\u003CString> testPublisher = TestPublisher.create();\n\n    StepVerifier.create(testPublisher.flux())\n        .then(() -> {\n            testPublisher.next(\"data\");\n            testPublisher.error(new RuntimeException(\"test error\"));\n        })\n        .expectNext(\"data\")\n        .expectError(RuntimeException.class)\n        .verify();\n}\n```\n\n\u003C\u002Fdetails>\n\n\u003Cdetails>\u003Csummary>WebTestClient — тестирование WebFlux-контроллеров\u003C\u002Fsummary>\n\n```java\n@WebFluxTest(UserController.class)\nclass UserControllerTest {\n\n    @Autowired\n    private WebTestClient webTestClient;\n\n    @MockitoBean\n    private UserService userService;\n\n    @Test\n    void shouldReturnUser() {\n        when(userService.findById(1L)).thenReturn(Mono.just(new User(1L, \"John\")));\n\n        webTestClient.get().uri(\"\u002Fapi\u002Fusers\u002F1\")\n            .exchange()\n            .expectStatus().isOk()\n            .expectBody(User.class)\n            .value(user -> assertThat(user.getName()).isEqualTo(\"John\"));\n    }\n\n    @Test\n    void shouldReturnAllUsers() {\n        when(userService.findAll()).thenReturn(Flux.just(\n            new User(1L, \"John\"), new User(2L, \"Jane\")));\n\n        webTestClient.get().uri(\"\u002Fapi\u002Fusers\")\n            .exchange()\n            .expectStatus().isOk()\n            .expectBodyList(User.class)\n            .hasSize(2);\n    }\n}\n```\n\n\u003C\u002Fdetails>\n\n### Частые ошибки\n\n- Забыть вызвать `.verify()` — StepVerifier не подпишется, тест будет «зелёным» без проверки\n- Использовать `.block()` вместо StepVerifier — теряется возможность проверки сигналов и порядка\n- Не использовать `withVirtualTime` для `interval`\u002F`delay` — тест будет ждать реальное время\n- Моки, возвращающие null — нужно возвращать `Mono.empty()` или `Flux.empty()`, а не null\n\n### Как используется в 2026\n\n- StepVerifier — стабильный стандарт де-факто\n- WebTestClient используется не только для WebFlux, но и для интеграционных тестов Spring MVC\n- Testcontainers + R2DBC — стандартная связка для интеграционных тестов реактивных репозиториев\n- AssertJ интеграция через StepVerifier + reactor-test\n\n> **На собеседовании:** минимум — знать StepVerifier и его основные методы (expectNext, verifyComplete, expectError). Частая ошибка — не упомянуть withVirtualTime для тестирования операторов с задержкой и WebTestClient для интеграционных тестов контроллеров.","","middle",[7],[],null,{"title":18,"description":19,"ogTitle":18,"ogDescription":20,"keywords":21,"schemaAnswer":22,"featuredSnippetReady":23},"Как тестировать реактивный код? — Gymterview","Реактивный код тестируется через StepVerifier — инструмент из reactor-test, который подписывается на Mono\u002FFlux и пошагово проверяет сигналы. Нельзя просто вызва","Реактивный код тестируется через StepVerifier — инструмент из reactor-test, который подписывается на Mono\u002FFlux и пошагов",[7,13],"Реактивный код тестируется через StepVerifier — инструмент из reactor-test, который подписывается на Mono\u002FFlux и пошагово проверяет сигналы. Нельзя просто вызвать метод и проверить результат, потому что Mono и Flux ленивы.",true]