async def test_resource_save_bad_request(generic_client, register_json): with Mocketizer(): register_json(HTTPretty.GET, '/users/1', json={ 'id': 1, 'username': '******', 'group': 'watchers', }) user1 = await generic_client.users.get(id=1) assert user1.username == 'user1' with Mocketizer(): register_json(HTTPretty.PUT, '/users/1', json={ 'status': 'error', }, status=400) register_json(HTTPretty.PATCH, '/users/1', json={ 'id': 1, 'username': '******', 'group': 'admins', }) user1.group = 'admins' await user1.save()
async def test_simpl_bulk_create(async_games_client, register_json): payload = [ { 'id': 1, 'username': '******', 'role': 'player', }, { 'id': 2, 'username': '******', 'role': 'player', }, ] with Mocketizer(): register_json(HTTPretty.POST, '/bulk/users/', json=payload, status=201) resources = await async_games_client.bulk.users.create(payload) assert resources is None with Mocketizer(): register_json(HTTPretty.POST, '/bulk/users/', json=payload, status=201) resources = await async_games_client.bulk.users.create(payload, return_ids=True) assert len(resources) == 2 assert resources[0] == 1 with Mocketizer(): register_json(HTTPretty.POST, '/bulk/users/', json=payload, status=500) with pytest.raises(async_games_client.HTTPError): await async_games_client.bulk.users.create(payload)
async def test_trailing_slash(api_url, register_json): generic_client = GenericClient(url=api_url) with Mocketizer(): register_json(HTTPretty.GET, '/users', json=[]) await generic_client.users.all() generic_client = GenericClient(url=api_url, trailing_slash=True) with Mocketizer(): register_json(HTTPretty.GET, '/users/', json=[]) await generic_client.users.all()
def test_intermittent_strict_mode(): url = "https://httpbin.org/ip" with Mocketizer(strict_mode=False): requests.get(url) with Mocketizer(strict_mode=True): with pytest.raises(StrictMocketException): requests.get(url) with Mocketizer(strict_mode=False): requests.get(url)
async def test_endpoint_list_route(generic_client, register_json, generic_response): with Mocketizer(): register_json(HTTPretty.POST, '/users/notify', **generic_response) response = await generic_client.users().notify(unread=3) assert response.data == 'ok' with Mocketizer(): register_json(HTTPretty.GET, '/users/notify', **generic_response) response = await generic_client.users(_method='get').notify(unread=3) assert response.data == 'ok'
def test_parse_cron_job_spec(self, dummy_host, batch_client): cron_job_list_with_info = { "items": [ { "spec": { "schedule": "*/5 * * * *", "concurrencyPolicy": "Allow", "jobTemplate": { "metadata": {}, "spec": { "template": { "metadata": {}, "spec": { "containers": [] }, }, }, }, }, }, ], } Entry.single_register( Entry.GET, f"{dummy_host}/apis/batch/v1/cronjobs", body=json.dumps(cron_job_list_with_info), headers={"content-type": "application/json"}, ) with Mocketizer(): cron_job = list( batch_client.list_cron_job_for_all_namespaces().items)[0] spec = parse_cron_job_spec(cron_job.spec) assert isinstance(spec.concurrency_policy, api.ConcurrencyPolicy) assert spec.schedule is not None assert spec.schedule == "*/5 * * * *"
def test_parse_status_failed_creation(self, apps_client, dummy_host): daemon_sets_data = { "items": [{ "status": { "currentNumberScheduled": 1, "numberMisscheduled": 0, "desiredNumberScheduled": 2, "numberReady": 0, "observedGeneration": 1, "updatedNumberScheduled": 1, "numberUnavailable": 1, } }] } Entry.single_register( Entry.GET, f"{dummy_host}/apis/apps/v1/daemonsets", body=json.dumps(daemon_sets_data), headers={"content-type": "application/json"}, ) with Mocketizer(): daemon_set = list( apps_client.list_daemon_set_for_all_namespaces().items)[0] status = parse_daemonset_status(daemon_set.status) assert status.number_misscheduled == 0 assert status.number_ready == 0 assert status.desired_number_scheduled == 2 assert status.updated_number_scheduled == 1
def test_parse_metadata_missing_annotations_and_labels( self, apps_client, dummy_host): daemon_sets_metadata = { "items": [{ "metadata": { "name": "node-collector-container-metrics", "namespace": "checkmk-monitoring", "uid": "6f07cb60-26c7-41ce-afe0-48c97d15a07b", "resourceVersion": "2967286", "generation": 1, "creationTimestamp": "2022-02-16T10:03:21Z", } }] } Entry.single_register( Entry.GET, f"{dummy_host}/apis/apps/v1/daemonsets", body=json.dumps(daemon_sets_metadata), headers={"content-type": "application/json"}, ) with Mocketizer(): daemon_set = list( apps_client.list_daemon_set_for_all_namespaces().items)[0] metadata = parse_metadata(daemon_set.metadata) assert metadata.labels == {} assert metadata.annotations == {}
def test_parse_status_no_matching_node(self, apps_client, dummy_host): """ Some DaemonSets may have no Nodes, on which they want to schedule Pods (because of their NodeSelector or NodeAffinity). In this case, some status fields are omitted. """ daemon_sets_data = { "items": [{ "status": { "currentNumberScheduled": 0, "numberMisscheduled": 0, "desiredNumberScheduled": 0, "numberReady": 0, "observedGeneration": 1, } }] } Entry.single_register( Entry.GET, f"{dummy_host}/apis/apps/v1/daemonsets", body=json.dumps(daemon_sets_data), headers={"content-type": "application/json"}, ) with Mocketizer(): daemon_set = list( apps_client.list_daemon_set_for_all_namespaces().items)[0] status = parse_daemonset_status(daemon_set.status) assert status.number_misscheduled == 0 assert status.number_ready == 0 assert status.desired_number_scheduled == 0 assert status.updated_number_scheduled == 0
async def test_simpl_bulk_delete(async_games_client, register_json): with Mocketizer(): register_json(HTTPretty.DELETE, '/bulk/users/?id__in=1&id__in=2', status=204) resources = await async_games_client.bulk.users.delete(id__in=[1, 2]) assert resources is None with Mocketizer(): register_json(HTTPretty.DELETE, '/bulk/users/?id__in=1&id__in=2', status=500) with pytest.raises(async_games_client.HTTPError): await async_games_client.bulk.users.delete(id__in=[1, 2])
async def test_simpl_bulk_unauthd(async_games_client, register_json): with Mocketizer(): register_json(HTTPretty.GET, '/bulk/users/', status=403) with pytest.raises(async_games_client.NotAuthenticatedError): resources = await async_games_client.bulk.users.all() assert resources is None
def test_parse_status_successful_creation(self, apps_client, dummy_host): statefulsets_data = { "items": [{ "status": { "observedGeneration": 1, "replicas": 3, "readyReplicas": 3, "currentReplicas": 3, "updatedReplicas": 3, "currentRevision": "web-578cfc4b46", "updateRevision": "web-578cfc4b46", "collisionCount": 0, "availableReplicas": 3, } }] } Entry.single_register( Entry.GET, f"{dummy_host}/apis/apps/v1/statefulsets", body=json.dumps(statefulsets_data), headers={"content-type": "application/json"}, ) with Mocketizer(): statefulset = list( apps_client.list_stateful_set_for_all_namespaces().items)[0] status = parse_statefulset_status(statefulset.status) assert status.ready_replicas == 3 assert status.updated_replicas == 3
def test_parse_metadata_missing_annotations_and_labels( self, apps_client, dummy_host): statefulsets_metadata = { "items": [{ "metadata": { "name": "web", "namespace": "default", "uid": "29be93ae-eba8-4b2b-8eb9-2e76378b4e87", "resourceVersion": "54122", "generation": 1, "creationTimestamp": "2022-03-09T07:44:17Z", }, }] } Entry.single_register( Entry.GET, f"{dummy_host}/apis/apps/v1/statefulsets", body=json.dumps(statefulsets_metadata), headers={"content-type": "application/json"}, ) with Mocketizer(): statefulset = list( apps_client.list_stateful_set_for_all_namespaces().items)[0] metadata = parse_metadata(statefulset.metadata) assert metadata.labels == {} assert metadata.annotations == {}
def test_parse_conditions(self, core_client, dummy_host): node_with_conditions = { "items": [ { "status": { "conditions": [ { "type": "Ready", "status": "False", "reason": None, "message": None, "lastTransitionTime": "2021-10-08T07:39:10Z", }, ], }, }, ], } Entry.single_register( Entry.GET, f"{dummy_host}/api/v1/pods", body=json.dumps(node_with_conditions), headers={"content-type": "application/json"}, ) with Mocketizer(): pod = list(core_client.list_pod_for_all_namespaces().items)[0] condition = pod_conditions(pod.status.conditions)[0] assert condition.detail is None assert condition.status is False assert condition.detail is None assert condition.type == api.ConditionType.READY
def test_parse_metadata_missing_annotations_and_labels(self, core_client, dummy_host): namespace_metadata = { "items": [ { "metadata": { "name": "checkmk-monitoring", "uid": "753292ba-5e0e-4267-a0f1-77a3c6b4d55e", "resourceVersion": "509", "creationTimestamp": "2022-03-25T13:24:42Z", }, }, ], } Entry.single_register( Entry.GET, f"{dummy_host}/api/v1/namespaces", body=json.dumps(namespace_metadata), headers={"content-type": "application/json"}, ) with Mocketizer(): namespace = list(core_client.list_namespace().items)[0] metadata = parse_namespace_metadata(namespace.metadata) assert metadata.labels == {} assert metadata.annotations == {}
async def test_endpoint_links(generic_client, register_json): with Mocketizer(): register_json( HTTPretty.GET, '/users?page=2', json=[ { 'id': 3, 'username': '******', 'group': 'watchers', }, { 'id': 4, 'username': '******', 'group': 'watchers', }, ], link= '<http://example.com/users?page=3>; rel=next,<http://example.com/users?page=1>; rel=previous', ) users = await generic_client.users.filter(page=2) assert users.response.links == { 'next': { 'url': 'http://example.com/users?page=3', 'rel': 'next' }, 'previous': { 'url': 'http://example.com/users?page=1', 'rel': 'previous' } }
async def test_endpoint_delete_httperror(generic_client, register_json): with Mocketizer(): register_json(HTTPretty.DELETE, '/users/1', status=500) with pytest.raises(generic_client.HTTPError): async with generic_client as session: await session.users.delete(1)
def test_parse_node_info(self, dummy_host, core_client): node_list_with_info = { "items": [{ "status": { "nodeInfo": { "machineID": "abd0bd9c2f234af099e849787da63620", "systemUUID": "e2902c84-10c9-4d81-b52b-85a27d62b7ca", "bootID": "04bae495-8ea7-4230-9bf0-9ce841201c0c", "kernelVersion": "5.4.0-88-generic", "osImage": "Ubuntu 20.04.3 LTS", "containerRuntimeVersion": "docker://20.10.7", "kubeletVersion": "v1.21.7", "kubeProxyVersion": "v1.21.7", "operatingSystem": "linux", "architecture": "amd64", }, }, }] } Entry.single_register( Entry.GET, f"{dummy_host}/api/v1/nodes", body=json.dumps(node_list_with_info), headers={"content-type": "application/json"}, ) with Mocketizer(): node = list(core_client.list_node().items)[0] parsed_node_info = node_info(node) assert isinstance(parsed_node_info, api.NodeInfo) assert parsed_node_info.kernel_version == "5.4.0-88-generic" assert parsed_node_info.os_image == "Ubuntu 20.04.3 LTS"
async def test_endpoint_delete_404(generic_client, register_json): with Mocketizer(): register_json(HTTPretty.DELETE, '/users/1', status=404) with pytest.raises(generic_client.ResourceNotFound): async with generic_client as session: await session.users.delete(1)
async def test_paginate(api_url, register_json): generic_client = GenericClient(url=api_url, autopaginate=link_header) with Mocketizer(): register_json( HTTPretty.GET, '/users', json=[{ 'id': 1 }], link='<{api_url}/users?page=2>; rel=next'.format(api_url=api_url)) register_json( HTTPretty.GET, '/users?page=2', json=[{ 'id': 2 }], link= '<{api_url}/users>; rel=previous, <{api_url}/users?page=3>; rel=next' .format(api_url=api_url)) register_json(HTTPretty.GET, '/users?page=3', json=[{ 'id': 3 }], link='<{api_url}/users?page=2>; rel=previous'.format( api_url=api_url)) users = await generic_client.users.all() assert len(users) == 3 assert users[0].id == 1 assert users[1].id == 2 assert users[2].id == 3
def test_parse_metadata_missing_annotations_and_labels( self, apps_client, dummy_host): mocked_deployments = { "items": [ { "metadata": { "name": "cluster-collector", "namespace": "checkmk-monitoring", "uid": "debc9fe4-9e45-4688-ad04-a95604fa1f30", "resourceVersion": "207264", "generation": 2, "creationTimestamp": "2022-03-25T13:24:42Z", }, }, ] } Entry.single_register( Entry.GET, f"{dummy_host}/apis/apps/v1/deployments", body=json.dumps(mocked_deployments), headers={"content-type": "application/json"}, ) with Mocketizer(): deployment = list( apps_client.list_deployment_for_all_namespaces().items)[0] metadata = parse_metadata(deployment.metadata) assert metadata.name == "cluster-collector" assert metadata.namespace == "checkmk-monitoring" assert isinstance(metadata.creation_timestamp, float) assert metadata.labels == {} assert metadata.annotations == {}
def test_real_request_session(): session = requests.Session() url1 = 'https://mockbin.com/ip' url2 = 'http://mockbin.com/request' with Mocketizer(): assert len(session.get(url1).content) < len(session.get(url2).content)
def test_real_request_session(): session = requests.Session() url1 = "https://httpbin.org/ip" url2 = "http://httpbin.org/headers" with Mocketizer(): assert len(session.get(url1).content) < len(session.get(url2).content)
def test_raw_api_get_healthz_ok(raw_api): Entry.single_register(Entry.GET, "http://api-unittest/some_health_endpoint", body="response-ok") with Mocketizer(): result = raw_api._get_healthz("/some_health_endpoint") assert result.status_code == 200 assert result.response == "response-ok" assert result.verbose_response is None
async def test_resource_delete(generic_client, register_json): with Mocketizer(): register_json(HTTPretty.GET, '/users/1', json={ 'id': 1, 'username': '******', 'group': 'watchers', }) user1 = await generic_client.users.get(id=1) assert user1.username == 'user1' with Mocketizer(): register_json(HTTPretty.DELETE, '/users/1', status=204) await user1.delete()
async def test_endpoint_filter(generic_client, register_json): with Mocketizer(): register_json(HTTPretty.GET, '/users?group=watchers', json=[ { 'id': 1, 'username': '******', 'group': 'watchers', }, { 'id': 2, 'username': '******', 'group': 'watchers', }, ]) async with generic_client as session: users = await session.users.filter(group="watchers") assert len(users) == 2 register_json(HTTPretty.GET, '/users?group__in=watchers&group__in=contributors', json=[ { 'id': 1, 'username': '******', 'group': 'watchers', }, { 'id': 2, 'username': '******', 'group': 'contributors', }, ]) async with generic_client as session: users = await session.users.filter( group__in=["watchers", "contributors"]) assert len(users) == 2 register_json(HTTPretty.GET, '/users?id__in=1&id__in=2', json=[ { 'id': 1, 'username': '******', 'group': 'watchers', }, { 'id': 2, 'username': '******', 'group': 'contributors', }, ]) users = await generic_client.users.filter(id__in=[1, 2]) assert len(users) == 2
async def test_simpl_get_id(async_games_client, register_json): with Mocketizer(): register_json(HTTPretty.GET, '/users/2/', json={ 'id': 2, 'username': '******', 'role': 'player', }) user2 = await async_games_client.users.get(id=2) assert user2.username == 'user2' with Mocketizer(): register_json(HTTPretty.GET, '/users/9999/', status=404) with pytest.raises(async_games_client.ResourceNotFound): await async_games_client.users.get(id=9999)
def test_socket_as_context_manager(self): addr = ("localhost", 80) Mocket.register(MocketEntry(addr, ["Show me.\r\n"])) with Mocketizer(): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as _so: _so.connect(addr) _so.sendall(encode_to_bytes("Whatever...")) data = _so.recv(4096) self.assertEqual(data, encode_to_bytes("Show me.\r\n"))
def test_makefile(self): addr = ("localhost", 80) Mocket.register(MocketEntry(addr, ["Show me.\r\n"])) with Mocketizer(): _so = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _so.connect(addr) fp = _so.makefile("rb") _so.sendall(encode_to_bytes("...\r\n")) self.assertEqual(fp.read().strip(), encode_to_bytes("Show me.")) self.assertEqual(len(Mocket.request_list()), 1)
def test_version_endpoint_no_json(raw_api): """ Invalid endpoint, since returned data is not json. RawAPI will not identify this issue. Instead, the issue needs to be handled seperately. """ Entry.single_register(Entry.GET, "http://api-unittest/version", body="I'm not json") with Mocketizer(): result = raw_api.query_raw_version() assert result == "I'm not json"