Coverage for tests / brokers / base / fastapi.py: 99%

415 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-05-08 01:48 +0000

1import asyncio 

2from contextlib import asynccontextmanager 

3from typing import Annotated, Any, TypeVar 

4from unittest.mock import Mock 

5 

6import pytest 

7from fastapi import BackgroundTasks, Depends, FastAPI, Header 

8from fastapi.exceptions import RequestValidationError 

9from fastapi.testclient import TestClient 

10 

11from faststream import ( 

12 Context as FSContext, 

13 Depends as FSDepends, 

14 Response, 

15) 

16from faststream._internal.broker import BrokerUsecase 

17from faststream._internal.broker.router import BrokerRouter 

18from faststream._internal.fastapi.context import Context 

19from faststream._internal.fastapi.route import StreamMessage 

20from faststream._internal.fastapi.router import StreamRouter 

21from faststream.exceptions import SetupError 

22 

23from .basic import BaseTestcaseConfig 

24 

25Broker = TypeVar("Broker", bound=BrokerUsecase) 

26 

27 

28@pytest.mark.asyncio() 

29class FastAPITestcase(BaseTestcaseConfig): 

30 router_class: type[StreamRouter[BrokerUsecase]] 

31 broker_router_class: type[BrokerRouter[Any]] 

32 

33 async def test_base_real(self, mock: Mock, queue: str) -> None: 

34 event = asyncio.Event() 

35 

36 router = self.router_class() 

37 

38 args, kwargs = self.get_subscriber_params(queue) 

39 

40 @router.subscriber(*args, **kwargs) 

41 async def hello(msg): 

42 event.set() 

43 return mock(msg) 

44 

45 async with router.broker: 

46 await router.broker.start() 

47 await asyncio.wait( 

48 ( 

49 asyncio.create_task(router.broker.publish("hi", queue)), 

50 asyncio.create_task(event.wait()), 

51 ), 

52 timeout=self.timeout, 

53 ) 

54 

55 assert event.is_set() 

56 mock.assert_called_with("hi") 

57 

58 async def test_background( 

59 self, 

60 mock: Mock, 

61 queue: str, 

62 event: asyncio.Event, 

63 ) -> None: 

64 router = self.router_class() 

65 

66 def task(msg: Any) -> None: 

67 event.set() 

68 return mock(msg) 

69 

70 args, kwargs = self.get_subscriber_params(queue) 

71 

72 @router.subscriber(*args, **kwargs) 

73 async def hello(msg, tasks: BackgroundTasks) -> None: 

74 tasks.add_task(task, msg) 

75 

76 async with router.broker: 

77 await router.broker.start() 

78 await asyncio.wait( 

79 ( 

80 asyncio.create_task(router.broker.publish("hi", queue)), 

81 asyncio.create_task(event.wait()), 

82 ), 

83 timeout=self.timeout, 

84 ) 

85 

86 mock.assert_called_with("hi") 

87 

88 async def test_context(self, mock: Mock, queue: str, event: asyncio.Event) -> None: 

89 router = self.router_class() 

90 context = router.context 

91 

92 context_key = "message.headers" 

93 

94 args, kwargs = self.get_subscriber_params(queue) 

95 

96 @router.subscriber(*args, **kwargs) 

97 async def hello(msg: Any = Context(context_key)) -> None: 

98 try: 

99 mock(msg == context.resolve(context_key) and msg["1"] == "1") 

100 finally: 

101 event.set() 

102 

103 async with router.broker: 

104 await router.broker.start() 

105 await asyncio.wait( 

106 ( 

107 asyncio.create_task( 

108 router.broker.publish("", queue, headers={"1": "1"}), 

109 ), 

110 asyncio.create_task(event.wait()), 

111 ), 

112 timeout=self.timeout, 

113 ) 

114 

115 assert event.is_set() 

116 mock.assert_called_with(True) 

117 

118 async def test_context_annotated( 

119 self, 

120 mock: Mock, 

121 queue: str, 

122 event: asyncio.Event, 

123 ) -> None: 

124 router = self.router_class() 

125 context = router.context 

126 

127 context_key = "message.headers" 

128 

129 args, kwargs = self.get_subscriber_params(queue) 

130 

131 @router.subscriber(*args, **kwargs) 

132 async def hello(msg: Annotated[Any, Context(context_key)]) -> None: 

133 try: 

134 mock(msg == context.resolve(context_key) and msg["1"] == "1") 

135 finally: 

136 event.set() 

137 

138 async with router.broker: 

139 await router.broker.start() 

140 await asyncio.wait( 

141 ( 

142 asyncio.create_task( 

143 router.broker.publish("", queue, headers={"1": "1"}), 

144 ), 

145 asyncio.create_task(event.wait()), 

146 ), 

147 timeout=self.timeout, 

148 ) 

149 

150 assert event.is_set() 

151 mock.assert_called_with(True) 

152 

153 @pytest.mark.flaky(reruns=3, reruns_delay=1) 

154 async def test_initial_context(self, queue: str, event: asyncio.Event) -> None: 

155 router = self.router_class() 

156 context = router.context 

157 

158 args, kwargs = self.get_subscriber_params(queue) 

159 

160 @router.subscriber(*args, **kwargs) 

161 async def hello(msg: int, data: set[int] = Context(queue, initial=set)) -> None: 

162 data.add(msg) 

163 if len(data) == 2: 

164 event.set() 

165 

166 async with router.broker: 

167 await router.broker.start() 

168 await asyncio.wait( 

169 ( 

170 asyncio.create_task(router.broker.publish(1, queue)), 

171 asyncio.create_task(router.broker.publish(2, queue)), 

172 asyncio.create_task(event.wait()), 

173 ), 

174 timeout=self.timeout, 

175 ) 

176 

177 assert context.get(queue) == {1, 2} 

178 context.reset_global(queue) 

179 

180 async def test_double_real(self, mock: Mock, queue: str) -> None: 

181 event = asyncio.Event() 

182 event2 = asyncio.Event() 

183 

184 router = self.router_class() 

185 

186 args, kwargs = self.get_subscriber_params(queue) 

187 sub1 = router.subscriber(*args, **kwargs) 

188 

189 args2, kwargs2 = self.get_subscriber_params(queue + "2") 

190 

191 @sub1 

192 @router.subscriber(*args2, **kwargs2) 

193 async def hello(msg: str) -> None: 

194 if event.is_set(): 

195 event2.set() 

196 else: 

197 event.set() 

198 mock() 

199 

200 async with router.broker: 

201 await router.broker.start() 

202 await asyncio.wait( 

203 ( 

204 asyncio.create_task(router.broker.publish("hi", queue)), 

205 asyncio.create_task(router.broker.publish("hi", queue + "2")), 

206 asyncio.create_task(event.wait()), 

207 asyncio.create_task(event2.wait()), 

208 ), 

209 timeout=self.timeout, 

210 ) 

211 

212 assert event.is_set() 

213 assert event2.is_set() 

214 assert mock.call_count == 2 

215 

216 async def test_base_publisher_real( 

217 self, 

218 mock: Mock, 

219 queue: str, 

220 ) -> None: 

221 event = asyncio.Event() 

222 

223 router = self.router_class() 

224 

225 args, kwargs = self.get_subscriber_params(queue) 

226 

227 @router.subscriber(*args, **kwargs) 

228 @router.publisher(queue + "resp") 

229 async def m() -> str: 

230 return "hi" 

231 

232 args2, kwargs2 = self.get_subscriber_params(queue + "resp") 

233 

234 @router.subscriber(*args2, **kwargs2) 

235 async def resp(msg) -> None: 

236 event.set() 

237 mock(msg) 

238 

239 async with router.broker: 

240 await router.broker.start() 

241 

242 await asyncio.wait( 

243 ( 

244 asyncio.create_task(router.broker.publish("", queue)), 

245 asyncio.create_task(event.wait()), 

246 ), 

247 timeout=self.timeout, 

248 ) 

249 

250 assert event.is_set() 

251 mock.assert_called_once_with("hi") 

252 

253 async def test_injection_fastapi( 

254 self, 

255 mock: Mock, 

256 queue: str, 

257 event: asyncio.Event, 

258 ) -> None: 

259 router = self.router_class() 

260 

261 args, kwargs = self.get_subscriber_params(queue) 

262 

263 @router.subscriber(*args, **kwargs) 

264 async def subscriber(msg: StreamMessage) -> None: 

265 mock("app" in msg.scope) 

266 event.set() 

267 

268 async with router.broker: 

269 await router.broker.start() 

270 await asyncio.wait( 

271 ( 

272 asyncio.create_task(router.broker.publish(None, queue)), 

273 asyncio.create_task(event.wait()), 

274 ), 

275 timeout=self.timeout, 

276 ) 

277 

278 mock.assert_called_once_with(True) 

279 

280 

281@pytest.mark.asyncio() 

282class FastAPILocalTestcase(BaseTestcaseConfig): 

283 router_class: type[StreamRouter[BrokerUsecase]] 

284 

285 async def test_base(self, queue: str) -> None: 

286 router = self.router_class() 

287 

288 app = FastAPI() 

289 app.include_router(router) 

290 

291 args, kwargs = self.get_subscriber_params(queue) 

292 

293 @router.subscriber(*args, **kwargs) 

294 async def hello() -> str: 

295 return "hi" 

296 

297 async with self.patch_broker(router.broker) as br: 

298 with TestClient(app) as client: 

299 assert client.app_state["broker"] is br 

300 

301 r = await br.request( 

302 "hi", 

303 queue, 

304 timeout=0.5, 

305 ) 

306 assert await r.decode() == "hi", r 

307 

308 async def test_request(self, queue: str) -> None: 

309 """Local test due request exists in all TestClients.""" 

310 router = self.router_class(setup_state=False) 

311 

312 app = FastAPI() 

313 

314 args, kwargs = self.get_subscriber_params(queue) 

315 

316 @router.subscriber(*args, **kwargs) 

317 async def hello(): 

318 return Response("Hi!", headers={"x-header": "test"}) 

319 

320 async with self.patch_broker(router.broker) as br: 

321 with TestClient(app) as client: 

322 assert not client.app_state.get("broker") 

323 

324 r = await br.request( 

325 "hi", 

326 queue, 

327 timeout=0.5, 

328 ) 

329 assert await r.decode() == "Hi!" 

330 assert r.headers["x-header"] == "test" 

331 

332 async def test_base_without_state(self, queue: str) -> None: 

333 router = self.router_class(setup_state=False) 

334 

335 app = FastAPI() 

336 

337 args, kwargs = self.get_subscriber_params(queue) 

338 

339 @router.subscriber(*args, **kwargs) 

340 async def hello() -> str: 

341 return "hi" 

342 

343 async with self.patch_broker(router.broker) as br: 

344 with TestClient(app) as client: 

345 assert not client.app_state.get("broker") 

346 

347 r = await br.request( 

348 "hi", 

349 queue, 

350 timeout=0.5, 

351 ) 

352 assert await r.decode() == "hi", r 

353 

354 async def test_invalid(self, queue: str) -> None: 

355 router = self.router_class() 

356 

357 app = FastAPI() 

358 

359 args, kwargs = self.get_subscriber_params(queue) 

360 

361 @router.subscriber(*args, **kwargs) 

362 async def hello(msg: int) -> None: ... 

363 

364 app.include_router(router) 

365 

366 async with self.patch_broker(router.broker) as br: 

367 with TestClient(app): 

368 with pytest.raises(RequestValidationError): 

369 await br.publish("hi", queue) 

370 

371 async def test_headers(self, queue: str) -> None: 

372 router = self.router_class() 

373 

374 args, kwargs = self.get_subscriber_params(queue) 

375 

376 @router.subscriber(*args, **kwargs) 

377 async def hello(w=Header()): 

378 return w 

379 

380 async with self.patch_broker(router.broker) as br: 

381 r = await br.request( 

382 "", 

383 queue, 

384 headers={"w": "hi"}, 

385 timeout=0.5, 

386 ) 

387 assert await r.decode() == "hi", r 

388 

389 async def test_depends(self, mock: Mock, queue: str) -> None: 

390 router = self.router_class() 

391 

392 def dep(a): 

393 mock(a) 

394 return a 

395 

396 args, kwargs = self.get_subscriber_params(queue) 

397 

398 @router.subscriber(*args, **kwargs) 

399 async def hello(a, w=Depends(dep)): 

400 return w 

401 

402 async with self.patch_broker(router.broker) as br: 

403 r = await br.request( 

404 {"a": "hi"}, 

405 queue, 

406 timeout=0.5, 

407 ) 

408 assert await r.decode() == "hi", r 

409 

410 mock.assert_called_once_with("hi") 

411 

412 async def test_mixed_depends(self, mock: Mock, queue: str) -> None: 

413 router = self.router_class() 

414 

415 def dep(a: str) -> str: 

416 mock(a) 

417 return a 

418 

419 args, kwargs = self.get_subscriber_params(queue) 

420 

421 @router.subscriber(*args, **kwargs) 

422 async def hello( 

423 a: str, 

424 w: Annotated[ 

425 str, 

426 Depends(dep), 

427 FSDepends(dep), # will be ignored 

428 ], 

429 ) -> str: 

430 return w 

431 

432 async with self.patch_broker(router.broker) as br: 

433 r = await br.request( 

434 {"a": "hi"}, 

435 queue, 

436 timeout=0.5, 

437 ) 

438 assert await r.decode() == "hi", r 

439 

440 mock.assert_called_once_with("hi") 

441 

442 async def test_depends_from_fastdepends_default(self, queue: str) -> None: 

443 router = self.router_class() 

444 

445 args, kwargs = self.get_subscriber_params(queue) 

446 

447 subscriber = router.subscriber(*args, **kwargs) 

448 

449 @subscriber 

450 def sub(d: Any = FSDepends(lambda: 1)) -> None: ... 

451 

452 app = FastAPI() 

453 app.include_router(router) 

454 

455 with pytest.raises(SetupError): # noqa: PT012 

456 async with self.patch_broker(router.broker): 

457 with TestClient(app): 

458 ... 

459 

460 async def test_depends_from_fastdepends_annotated(self, queue: str) -> None: 

461 router = self.router_class() 

462 

463 args, kwargs = self.get_subscriber_params(queue) 

464 

465 subscriber = router.subscriber(*args, **kwargs) 

466 

467 @subscriber 

468 def sub(d: Annotated[Any, FSDepends(lambda: 1)]) -> None: ... 

469 

470 app = FastAPI() 

471 app.include_router(router) 

472 

473 with pytest.raises(SetupError): # noqa: PT012 

474 async with self.patch_broker(router.broker): 

475 with TestClient(app): 

476 ... 

477 

478 async def test_depends_combined_annotated(self, queue: str) -> None: 

479 router = self.router_class() 

480 

481 args, kwargs = self.get_subscriber_params(queue) 

482 

483 subscriber = router.subscriber(*args, **kwargs) 

484 

485 @subscriber 

486 def sub( 

487 d: Annotated[Any, FSDepends(lambda: 1), Depends(lambda: 1)], 

488 ) -> None: ... 

489 

490 app = FastAPI() 

491 app.include_router(router) 

492 

493 async with self.patch_broker(router.broker): 

494 with TestClient(app): 

495 ... 

496 

497 async def test_faststream_context(self, queue: str) -> None: 

498 router = self.router_class() 

499 

500 args, kwargs = self.get_subscriber_params(queue) 

501 

502 @router.subscriber(*args, **kwargs) 

503 async def hello(msg: Any = FSContext()) -> None: ... 

504 

505 app = FastAPI() 

506 app.include_router(router) 

507 

508 with pytest.raises(SetupError): # noqa: PT012 

509 async with self.patch_broker(router.broker): 

510 with TestClient(app): 

511 ... 

512 

513 async def test_faststream_context_annotated(self, queue: str) -> None: 

514 router = self.router_class() 

515 

516 args, kwargs = self.get_subscriber_params(queue) 

517 

518 @router.subscriber(*args, **kwargs) 

519 async def hello(msg: Annotated[Any, FSContext()]) -> None: ... 

520 

521 app = FastAPI() 

522 app.include_router(router) 

523 

524 with pytest.raises(SetupError): # noqa: PT012 

525 async with self.patch_broker(router.broker): 

526 with TestClient(app): 

527 ... 

528 

529 async def test_combined_context_annotated(self, queue: str) -> None: 

530 router = self.router_class() 

531 

532 args, kwargs = self.get_subscriber_params(queue) 

533 

534 @router.subscriber(*args, **kwargs) 

535 async def hello( 

536 msg: Annotated[ 

537 Any, 

538 Context("message.headers"), 

539 FSContext("message.headers"), 

540 ], 

541 ) -> None: ... 

542 

543 app = FastAPI() 

544 app.include_router(router) 

545 

546 async with self.patch_broker(router.broker): 

547 with TestClient(app): 

548 ... 

549 

550 async def test_nested_combined_context_annotated(self, queue: str) -> None: 

551 router = self.router_class() 

552 

553 args, kwargs = self.get_subscriber_params(queue) 

554 

555 @router.subscriber(*args, **kwargs) 

556 async def hello( 

557 msg: Annotated[ 

558 Annotated[Any, FSContext("message.headers")], 

559 Context("message.headers"), 

560 ], 

561 ) -> None: ... 

562 

563 app = FastAPI() 

564 app.include_router(router) 

565 

566 async with self.patch_broker(router.broker): 

567 with TestClient(app): 

568 ... 

569 

570 async def test_yield_depends(self, mock: Mock, queue: str) -> None: 

571 router = self.router_class() 

572 

573 def dep(a): 

574 mock.start() 

575 yield a 

576 mock.close() 

577 

578 args, kwargs = self.get_subscriber_params(queue) 

579 

580 @router.subscriber(*args, **kwargs) 

581 async def hello(a, w=Depends(dep)): 

582 mock.start.assert_called_once() 

583 assert not mock.close.call_count 

584 return w 

585 

586 async with self.patch_broker(router.broker) as br: 

587 r = await br.request( 

588 {"a": "hi"}, 

589 queue, 

590 timeout=0.5, 

591 ) 

592 assert await r.decode() == "hi", r 

593 

594 mock.start.assert_called_once() 

595 mock.close.assert_called_once() 

596 

597 async def test_router_depends(self, mock: Mock, queue: str) -> None: 

598 def mock_dep() -> None: 

599 mock() 

600 

601 router = self.router_class(dependencies=(Depends(mock_dep, use_cache=False),)) 

602 

603 args, kwargs = self.get_subscriber_params(queue) 

604 

605 @router.subscriber(*args, **kwargs) 

606 async def hello(a): 

607 return a 

608 

609 async with self.patch_broker(router.broker) as br: 

610 r = await br.request("hi", queue, timeout=0.5) 

611 assert await r.decode() == "hi", r 

612 

613 mock.assert_called_once() 

614 

615 async def test_subscriber_depends(self, mock: Mock, queue: str) -> None: 

616 def mock_dep() -> None: 

617 mock() 

618 

619 router = self.router_class() 

620 

621 args, kwargs = self.get_subscriber_params( 

622 queue, 

623 dependencies=(Depends(mock_dep, use_cache=False),), 

624 ) 

625 

626 @router.subscriber(*args, **kwargs) 

627 async def hello(a): 

628 return a 

629 

630 async with self.patch_broker(router.broker) as br: 

631 r = await br.request( 

632 "hi", 

633 queue, 

634 timeout=0.5, 

635 ) 

636 assert await r.decode() == "hi", r 

637 

638 mock.assert_called_once() 

639 

640 async def test_hooks(self, mock: Mock) -> None: 

641 router = self.router_class() 

642 

643 app = FastAPI() 

644 app.include_router(router) 

645 

646 @router.after_startup 

647 def test_sync(app) -> None: 

648 mock.sync_called() 

649 

650 @router.after_startup 

651 async def test_async(app) -> None: 

652 mock.async_called() 

653 

654 @router.on_broker_shutdown 

655 def test_shutdown_sync(app) -> None: 

656 mock.sync_shutdown_called() 

657 

658 @router.on_broker_shutdown 

659 async def test_shutdown_async(app) -> None: 

660 mock.async_shutdown_called() 

661 

662 async with self.patch_broker(router.broker), router.lifespan_context(app): 

663 pass 

664 

665 mock.sync_called.assert_called_once() 

666 mock.async_called.assert_called_once() 

667 mock.sync_shutdown_called.assert_called_once() 

668 mock.async_shutdown_called.assert_called_once() 

669 

670 async def test_existed_lifespan_startup(self, mock: Mock) -> None: 

671 @asynccontextmanager 

672 async def lifespan(app): 

673 mock.start() 

674 yield {"lifespan": True} 

675 mock.close() 

676 

677 router = self.router_class(lifespan=lifespan) 

678 

679 app = FastAPI() 

680 app.include_router(router) 

681 

682 async with ( 

683 self.patch_broker(router.broker), 

684 router.lifespan_context( 

685 app, 

686 ) as context, 

687 ): 

688 assert context["lifespan"] 

689 

690 mock.start.assert_called_once() 

691 mock.close.assert_called_once() 

692 

693 async def test_subscriber_mock(self, queue: str) -> None: 

694 router = self.router_class() 

695 

696 args, kwargs = self.get_subscriber_params(queue) 

697 

698 @router.subscriber(*args, **kwargs) 

699 async def m() -> str: 

700 return "hi" 

701 

702 async with self.patch_broker(router.broker) as rb: 

703 await rb.publish("hello", queue) 

704 m.mock.assert_called_once_with("hello") 

705 

706 async def test_publisher_mock(self, queue: str) -> None: 

707 router = self.router_class() 

708 

709 publisher = router.publisher(queue + "resp") 

710 

711 args, kwargs = self.get_subscriber_params(queue) 

712 sub = router.subscriber(*args, **kwargs) 

713 

714 @publisher 

715 @sub 

716 async def m() -> str: 

717 return "response" 

718 

719 async with self.patch_broker(router.broker) as rb: 

720 await rb.publish("hello", queue) 

721 publisher.mock.assert_called_with("response") 

722 

723 async def test_include(self, queue: str) -> None: 

724 router = self.router_class() 

725 router2 = self.broker_router_class() 

726 

727 app = FastAPI() 

728 

729 args, kwargs = self.get_subscriber_params(queue) 

730 

731 @router.subscriber(*args, **kwargs) 

732 async def hello() -> str: 

733 return "hi" 

734 

735 args2, kwargs2 = self.get_subscriber_params(queue + "1") 

736 

737 @router2.subscriber(*args2, **kwargs2) 

738 async def hello_router2() -> str: 

739 return "hi" 

740 

741 router.include_router(router2) 

742 app.include_router(router) 

743 

744 async with self.patch_broker(router.broker) as br: 

745 with TestClient(app) as client: 

746 assert client.app_state["broker"] is br 

747 

748 r = await br.request( 

749 "hi", 

750 queue, 

751 timeout=0.5, 

752 ) 

753 assert await r.decode() == "hi", r 

754 

755 r = await br.request( 

756 "hi", 

757 queue + "1", 

758 timeout=0.5, 

759 ) 

760 assert await r.decode() == "hi", r 

761 

762 async def test_dependency_overrides(self, mock: Mock, queue: str) -> None: 

763 router = self.router_class() 

764 

765 def dep1() -> None: 

766 raise AssertionError 

767 

768 def dep2() -> None: 

769 mock() 

770 

771 app = FastAPI() 

772 app.dependency_overrides[dep1] = dep2 

773 

774 args, kwargs = self.get_subscriber_params(queue) 

775 

776 @router.subscriber(*args, **kwargs) 

777 async def hello_router2(dep: None = Depends(dep1)) -> str: 

778 return "hi" 

779 

780 app.include_router(router) 

781 

782 async with self.patch_broker(router.broker) as br: 

783 with TestClient(app) as client: 

784 assert client.app_state["broker"] is br 

785 

786 r = await br.request( 

787 "hi", 

788 queue, 

789 timeout=0.5, 

790 ) 

791 assert await r.decode() == "hi", r 

792 

793 mock.assert_called_once() 

794 

795 async def test_nested_router(self, queue: str) -> None: 

796 router = self.router_class() 

797 router2 = self.router_class() 

798 

799 args, kwargs = self.get_subscriber_params(queue) 

800 

801 @router2.subscriber(*args, **kwargs) 

802 async def hello_router2() -> str: 

803 return "hi" 

804 

805 with pytest.raises( 

806 TypeError, 

807 match="Including a StreamRouter into another StreamRouter", 

808 ): 

809 router.include_router(router2) 

810 

811 def test_nested_stream_router_raises( 

812 self, 

813 queue: str, 

814 ) -> None: 

815 """Including a StreamRouter into another StreamRouter must raise TypeError. 

816 

817 This pattern is unsupported (issue #2657). Users should include a regular 

818 broker router (e.g. KafkaRouter) into the StreamRouter instead. 

819 """ 

820 router = self.router_class() 

821 router2 = self.router_class() 

822 

823 with pytest.raises( 

824 TypeError, 

825 match="Including a StreamRouter into another StreamRouter is not supported", 

826 ): 

827 router.include_router(router2)