Class that lets you create mock ASGI-like Request objects for use in testing. Usage: rf = AsyncRequestFactory() get_request = rf.get("/hello/") post_request = rf.post("/submit/", {"foo": "bar"}) Once you have a request object you can pass it to any view function, inclu
| 672 | |
| 673 | |
| 674 | class AsyncRequestFactory(RequestFactory): |
| 675 | """ |
| 676 | Class that lets you create mock ASGI-like Request objects for use in |
| 677 | testing. Usage: |
| 678 | |
| 679 | rf = AsyncRequestFactory() |
| 680 | get_request = rf.get("/hello/") |
| 681 | post_request = rf.post("/submit/", {"foo": "bar"}) |
| 682 | |
| 683 | Once you have a request object you can pass it to any view function, |
| 684 | including synchronous ones. The reason we have a separate class here is: |
| 685 | a) this makes ASGIRequest subclasses, and |
| 686 | b) AsyncClient can subclass it. |
| 687 | """ |
| 688 | |
| 689 | def _base_scope(self, **request): |
| 690 | """The base scope for a request.""" |
| 691 | # This is a minimal valid ASGI scope, plus: |
| 692 | # - headers['cookie'] for cookie support, |
| 693 | # - 'client' often useful, see #8551. |
| 694 | scope = { |
| 695 | "asgi": {"version": "3.0"}, |
| 696 | "type": "http", |
| 697 | "http_version": "1.1", |
| 698 | "client": ["127.0.0.1", 0], |
| 699 | "server": ("testserver", "80"), |
| 700 | "scheme": "http", |
| 701 | "method": "GET", |
| 702 | "headers": [], |
| 703 | **self.defaults, |
| 704 | **request, |
| 705 | } |
| 706 | scope["headers"].append( |
| 707 | ( |
| 708 | b"cookie", |
| 709 | b"; ".join( |
| 710 | sorted( |
| 711 | ("%s=%s" % (morsel.key, morsel.coded_value)).encode("ascii") |
| 712 | for morsel in self.cookies.values() |
| 713 | ) |
| 714 | ), |
| 715 | ) |
| 716 | ) |
| 717 | return scope |
| 718 | |
| 719 | def request(self, **request): |
| 720 | """Construct a generic request object.""" |
| 721 | # This is synchronous, which means all methods on this class are. |
| 722 | # AsyncClient, however, has an async request function, which makes all |
| 723 | # its methods async. |
| 724 | if "_body_file" in request: |
| 725 | body_file = request.pop("_body_file") |
| 726 | else: |
| 727 | body_file = FakePayload("") |
| 728 | # Wrap FakePayload body_file to allow large read() in test environment. |
| 729 | return ASGIRequest( |
| 730 | self._base_scope(**request), LimitedStream(body_file, len(body_file)) |
| 731 | ) |
no outgoing calls