如何使用 Python 3.7 模拟 Google API 库以进行单元测试

问题描述 投票:0回答:3

我正在尝试创建一组单元测试来测试 Bigquery 的 Google 客户端库。我正在努力制作一个单元测试文件,该文件将模拟客户端并让我测试我的输入。我提供了一个简单的脚本,其中包含一些设置功能,用于返回属于数据集的表列表。

有人可以向我展示一个模拟 Google 客户端库作为我找到的文档的示例吗@ https://github.com/googleapis/google-cloud-python/blob/master/bigquery/tests/unit/test_client。 py 不直接与代码的方法交互,因此我无法将其应用到我的代码中。

感谢任何实现此目的的想法或方法,我似乎无法在 Stack Overflow 上找到任何记录此问题的地方。

谢谢

from google.cloud import bigquery


def get_dataset():
    client = bigquery.Client.from_service_account_json('some_client_secret.json')

    dataset_id = 'some_project.some_dataset'

    dataset = client.get_dataset(dataset_id)

    full_dataset_id = "{}.{}".format(dataset.project, dataset.dataset_id)
    friendly_name = dataset.friendly_name
    print(
        "Got dataset '{}' with friendly_name '{}'.".format(
            full_dataset_id, friendly_name
        )
    )

    # View dataset properties
    print("Description: {}".format(dataset.description))
    print("Labels:")
    labels = dataset.labels
    if labels:
        for label, value in labels.items():
            print("\t{}: {}".format(label, value))
    else:
        print("\tDataset has no labels defined.")

    # View tables in dataset
    print("Tables:")
    tables = list(client.list_tables(dataset))  # API request(s)
    if tables:
        for table in tables:
            print("\t{}".format(table.table_id))
    else:
        print("\tThis dataset does not contain any tables.")
python-3.x unit-testing google-app-engine mocking google-client
3个回答
36
投票

我花了相当多的谷歌搜索和反复试验才弄清楚如何做到这一点,而且我刚刚开始工作,所以我认为值得分享。

unittest
提供了
patch
,它允许您在使用时模拟函数,即。替换测试代码中的 Google API 调用,以及 mock
,它允许您进一步自定义在该模拟上访问属性和调用函数的结果。

unittest

 文档解释了此处的修补:
https://docs.python.org/3/library/unittest.mock.html#where-to-patch

这确实解释了它是如何工作的,但为了理解如何正确执行此操作,我发现的最佳解释是:

http://alexmarandon.com/articles/python_mock_gotchas/

这是一个要测试的 Python 脚本,

mocking_google.py

,其中包含对 Google Storage 和 BigQuery API 的引用:

from google.cloud.bigquery import Client as bigqueryClient from google.cloud.storage import Client as storageClient def list_blobs(): storage_client = storageClient(project='test') blobs = storage_client.list_blobs('bucket', prefix='prefix') return blobs def extract_table(): bigquery_client = bigqueryClient(project='test') job = bigquery_client.extract_table('project.dataset.table_id', destination_uris='uri') return job

这是单元测试:

import pytest from unittest.mock import Mock, patch from src.data.mocking_google import list_blobs, extract_table @pytest.fixture def extract_result(): 'Mock extract_job result with properties needed' er = Mock() er.return_value = 1 return er @pytest.fixture def extract_job(extract_result): 'Mock extract_job with properties needed' ej = Mock() ej.job_id = 1 ej.result.return_value = 2 return ej @patch("src.data.mocking_google.storageClient") def test_list_blobs(storageClient): storageClient().list_blobs.return_value = [1,2] blob_list = list_blobs() storageClient().list_blobs.assert_called_with('bucket', prefix='prefix') assert blob_list == [1,2] @patch("src.data.mocking_google.bigqueryClient") def test_extract_table(bigqueryClient,extract_job): bigqueryClient().extract_table.return_value = extract_job job = extract_table() bigqueryClient().extract_table.assert_called_with('project.dataset.table_id', destination_uris='uri') assert job.job_id == 1 assert job.result() == 2

这是测试结果:

pytest -v src/tests/data/test_mocking_google.py============================================================ test session starts ============================================================= platform darwin -- Python 3.7.6, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 -- /Users/gaya/.local/share/virtualenvs/autoencoder-recommendation-copy-zpYZ6J1x/bin/python3 cachedir: .pytest_cache rootdir: /Users/gaya/Documents/GitHub/mlops-autoencoder-recommendation, inifile: tox.ini plugins: cov-2.8.1 collected 2 items src/tests/data/test_mocking_google.py::test_list_blobs PASSED [ 50%] src/tests/data/test_mocking_google.py::test_extract_table PASSED [100%] ============================================================= 2 passed in 1.14s ==============================================================

如果不清楚其工作原理,很乐意进一步解释:)


8
投票
我还发现很难绕过身份验证部分,并且只能模拟与方法的交互,所以我最终只是模拟了整个库。 :捂脸:

import sys from unittest.mock import MagicMock sys.modules["google.cloud.storage"] = MagicMock() from your_application import make_app def test_make_app(): make_app()
    

0
投票

https://github.com/googleapis/google-cloud-python/tree/main/packages/{PACKAGE}/ 很棒的信息。谢谢大家。

© www.soinside.com 2019 - 2024. All rights reserved.