Unit Test¶
If you are using githubkit in your business logic, you may want to mock the github API in your unit tests. There are two ways to reach this.
Mocking the API Calls¶
If you can't provide a githubkit test client to your business logic, you can mock the request/arequest method of the GitHub class to custom the response. Here is an example of how to mock githubkit's API calls:
import json
from pathlib import Path
from typing import Any, Type, Union
import httpx
import pytest
from githubkit import GitHub
from githubkit.utils import UNSET
from githubkit.response import Response
from githubkit.typing import URLTypes, UnsetType
from githubkit.versions.latest.models import FullRepository
FAKE_RESPONSE = json.loads(Path("fake_response.json").read_text())
def target_sync_func() -> FullRepository: # (1)!
github = GitHub("xxxxx")
resp = github.rest.repos.get("owner", "repo")
return resp.parsed_data
def mock_request(
g: GitHub,
method: str,
url: URLTypes,
*,
response_model: Union[Type[Any], UnsetType] = UNSET,
**kwargs: Any, # (2)!
) -> Response[Any]:
if method == "GET" and url == "/repos/owner/repo": # (3)!
return Response(
httpx.Response(status_code=200, json=FAKE_RESPONSE),
Any if response_model is UNSET else response_model,
)
raise RuntimeError(f"Unexpected request: {method} {url}")
# Test the target function
def test_sync_mock():
with pytest.MonkeyPatch.context() as m:
# Patch the request method with the mock
m.setattr(GitHub, "request", mock_request)
repo = target_sync_func()
assert isinstance(repo, FullRepository)
- Example function you want to test, which calls the GitHub API.
- other request parameters including headers, json, etc.
- When the request is made, return a fake response
import json
from pathlib import Path
from typing import Any, Type, Union
import httpx
import pytest
from githubkit import GitHub
from githubkit.utils import UNSET
from githubkit.response import Response
from githubkit.typing import URLTypes, UnsetType
from githubkit.versions.latest.models import FullRepository
FAKE_RESPONSE = json.loads(Path("fake_response.json").read_text())
async def target_async_func() -> FullRepository: # (1)!
async with GitHub("xxxxx") as github:
resp = await github.rest.repos.get("owner", "repo")
return resp.parsed_data
async def mock_arequest(
g: GitHub,
method: str,
url: URLTypes,
*,
response_model: Union[Type[Any], UnsetType] = UNSET,
**kwargs: Any, # (2)!
) -> Response[Any]:
if method == "GET" and url == "/repos/owner/repo": # (3)!
return Response(
httpx.Response(status_code=200, json=FAKE_RESPONSE),
Any if response_model is UNSET else response_model,
)
raise RuntimeError(f"Unexpected request: {method} {url}")
# Test the target function
@pytest.mark.anyio
async def test_async_mock():
with pytest.MonkeyPatch.context() as m:
# Patch the request method with the mock
m.setattr(GitHub, "arequest", mock_arequest)
repo = await target_async_func()
assert isinstance(repo, FullRepository)
- Example function you want to test, which calls the GitHub API.
- other request parameters including headers, json, etc.
- When the request is made, return a fake response
Using a Test Transport¶
You can also create a test client with mock transport and provide it to your business logic. Here is an example:
import json
from pathlib import Path
import httpx
import pytest
from githubkit import GitHub
from githubkit.versions.latest.models import FullRepository
FAKE_RESPONSE = json.loads(Path("fake_response.json").read_text())
def target_sync_func(github: GitHub):
resp = github.rest.repos.get("owner", "repo")
return resp.parsed_data
def mock_transport_handler(request: httpx.Request) -> httpx.Response:
if request.method == "GET" and request.url.path == "/repos/owner/repo":
return httpx.Response(status_code=200, json=FAKE_RESPONSE)
raise RuntimeError(f"Unexpected request: {request.method} {request.url.path}")
def test_sync_mock():
g = GitHub("xxxxx", transport=httpx.MockTransport(mock_transport_handler))
repo = target_sync_func(g)
assert isinstance(repo, FullRepository)
import json
from pathlib import Path
import httpx
import pytest
from githubkit import GitHub
from githubkit.versions.latest.models import FullRepository
FAKE_RESPONSE = json.loads(Path("fake_response.json").read_text())
async def target_async_func(github: GitHub):
resp = await github.rest.repos.async_get("owner", "repo")
return resp.parsed_data
def mock_transport_handler(request: httpx.Request) -> httpx.Response:
if request.method == "GET" and request.url.path == "/repos/owner/repo":
return httpx.Response(status_code=200, json=FAKE_RESPONSE)
raise RuntimeError(f"Unexpected request: {request.method} {request.url.path}")
@pytest.mark.anyio
async def test_async_mock():
g = GitHub("xxxxx", async_transport=httpx.MockTransport(mock_transport_handler))
repo = await target_async_func(g)
assert isinstance(repo, FullRepository)